diff options
author | Ingela Anderton Andin <[email protected]> | 2013-04-17 10:28:25 +0200 |
---|---|---|
committer | Ingela Anderton Andin <[email protected]> | 2013-05-08 10:39:18 +0200 |
commit | dfd9c13f882ef199dfcb830823cb12d83bcc4f10 (patch) | |
tree | dc99edce4ec3f01f1ab40cd1dde2256637e82ded /lib/ssl/src | |
parent | d565a551ff2605c8abca0009ab90fbb7687a4097 (diff) | |
download | otp-dfd9c13f882ef199dfcb830823cb12d83bcc4f10.tar.gz otp-dfd9c13f882ef199dfcb830823cb12d83bcc4f10.tar.bz2 otp-dfd9c13f882ef199dfcb830823cb12d83bcc4f10.zip |
ssl & public_key: New public_key API for DH/ECDH/SRP keys
Diffstat (limited to 'lib/ssl/src')
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 104 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 16 |
2 files changed, 42 insertions, 78 deletions
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index aa02c47a3d..dc9ab89331 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -685,8 +685,8 @@ certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPubl certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientPublicEcDhPoint}, #state{negotiated_version = Version, - diffie_hellman_keys = {'ECKey', ECDHKey}} = State0) -> - case ec_dh_master_secret(ECDHKey, ClientPublicEcDhPoint, State0) of + diffie_hellman_keys = ECDHKey} = State0) -> + case ec_dh_master_secret(ECDHKey, #'ECPoint'{point = ClientPublicEcDhPoint}, State0) of #state{} = State1 -> {Record, State} = next_record(State1), next_state(certify, cipher, Record, State); @@ -1325,28 +1325,9 @@ private_key(#'PrivateKeyInfo'{privateKeyAlgorithm = privateKey = Key}) -> public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key)); -private_key(#'ECPrivateKey'{privateKey = PrivKey, - parameters = Param, - publicKey = _PubKey}) -> - ECCurve = case Param of - #'OTPECParameters'{ fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor } -> - Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'OTPFieldID'.fieldType), FieldId#'OTPFieldID'.parameters}, - Curve = {list2int(PCurve#'Curve'.a), list2int(PCurve#'Curve'.b), none}, - {Field, Curve, erlang:list_to_binary(Base), Order, CoFactor}; - {namedCurve, OID} -> - pubkey_cert_records:namedCurves(OID) - end, - Key = {ECCurve, list2int(PrivKey), undefined}, - {'ECKey', crypto:term_to_ec_key(Key)}; - private_key(Key) -> Key. -list2int(L) -> - S = length(L) * 8, - <<R:S/integer>> = erlang:iolist_to_binary(L), - R. - -spec(file_error(_,_) -> no_return()). file_error(File, Throw) -> case Throw of @@ -1396,20 +1377,10 @@ handle_peer_cert(PeerCert, PublicKeyInfo, Session#session{peer_certificate = PeerCert}, public_key_info = PublicKeyInfo}, State2 = case PublicKeyInfo of - {?'id-ecPublicKey', {'ECPoint', PublicKey}, PublicKeyParams} -> - ECCurve = case PublicKeyParams of - #'OTPECParameters'{ fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor } -> - Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'OTPFieldID'.fieldType), FieldId#'OTPFieldID'.parameters}, - Curve = {list2int(PCurve#'Curve'.a), list2int(PCurve#'Curve'.b), none}, - {Field, Curve, erlang:list_to_binary(Base), Order, CoFactor}; - {namedCurve, OID} -> - pubkey_cert_records:namedCurves(OID) - end, - %% Generate Client ECDH Key - ECClntKey = crypto:ec_key_new(ECCurve), - crypto:ec_key_generate(ECClntKey), - State3 = State1#state{diffie_hellman_keys = {'ECKey', ECClntKey}}, - ec_dh_master_secret(ECClntKey, PublicKey, State3); + {?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey, PublicKeyParams} -> + Keys = public_key:generate_key(PublicKey, PublicKeyParams), + State3 = State1#state{diffie_hellman_keys = Keys}, + ec_dh_master_secret(Keys, PublicKey, State3); _ -> State1 end, @@ -1633,7 +1604,7 @@ key_exchange(#state{role = server, key_algorithm = rsa} = State) -> State; key_exchange(#state{role = server, key_algorithm = Algo, hashsign_algorithm = HashSignAlgo, - diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params, + diffie_hellman_params = #'DHParameter'{} = Params, private_key = PrivateKey, connection_states = ConnectionStates0, negotiated_version = Version, @@ -1644,7 +1615,7 @@ key_exchange(#state{role = server, key_algorithm = Algo, when Algo == dhe_dss; Algo == dhe_rsa; Algo == dh_anon -> - Keys = crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]), + Keys = public_key:generate_key(Params), ConnectionState = ssl_record:pending_connection_state(ConnectionStates0, read), SecParams = ConnectionState#connection_state.security_parameters, @@ -1663,7 +1634,8 @@ key_exchange(#state{role = server, key_algorithm = Algo, key_exchange(#state{role = server, private_key = Key, key_algorithm = Algo} = State) when Algo == ecdh_ecdsa; Algo == ecdh_rsa -> - State#state{diffie_hellman_keys = Key}; + ECDH = public_key:generate_key(Key), + State#state{diffie_hellman_keys = ECDH}; key_exchange(#state{role = server, key_algorithm = Algo, hashsign_algorithm = HashSignAlgo, private_key = PrivateKey, @@ -1675,19 +1647,14 @@ key_exchange(#state{role = server, key_algorithm = Algo, } = State) when Algo == ecdhe_ecdsa; Algo == ecdhe_rsa; Algo == ecdh_anon -> - %%TODO: select prefered curve from extension - - %% Generate Server ECDH Key - ECDHKey = crypto:ec_key_new(secp256k1), - crypto:ec_key_generate(ECDHKey), - Keys = {'ECKey', ECDHKey}, + ECDHKey = public_key:generate_key({curve, default_curve(State)}), ConnectionState = ssl_record:pending_connection_state(ConnectionStates0, read), SecParams = ConnectionState#connection_state.security_parameters, #security_parameters{client_random = ClientRandom, server_random = ServerRandom} = SecParams, - Msg = ssl_handshake:key_exchange(server, Version, {ecdh, Keys, + Msg = ssl_handshake:key_exchange(server, Version, {ecdh, ECDHKey, HashSignAlgo, ClientRandom, ServerRandom, PrivateKey}), @@ -1695,7 +1662,7 @@ key_exchange(#state{role = server, key_algorithm = Algo, encode_handshake(Msg, Version, ConnectionStates0, Handshake0), Transport:send(Socket, BinMsg), State#state{connection_states = ConnectionStates, - diffie_hellman_keys = Keys, + diffie_hellman_keys = ECDHKey, tls_handshake_history = Handshake1}; key_exchange(#state{role = server, key_algorithm = psk, @@ -1729,7 +1696,7 @@ key_exchange(#state{role = server, key_algorithm = psk, key_exchange(#state{role = server, key_algorithm = dhe_psk, ssl_options = #ssl_options{psk_identity = PskIdentityHint}, hashsign_algorithm = HashSignAlgo, - diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params, + diffie_hellman_params = #'DHParameter'{} = Params, private_key = PrivateKey, connection_states = ConnectionStates0, negotiated_version = Version, @@ -1737,7 +1704,7 @@ key_exchange(#state{role = server, key_algorithm = dhe_psk, socket = Socket, transport_cb = Transport } = State) -> - Keys = crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]), + Keys = public_key:generate_key(Params), ConnectionState = ssl_record:pending_connection_state(ConnectionStates0, read), SecParams = ConnectionState#connection_state.security_parameters, @@ -2084,12 +2051,8 @@ server_master_secret(#server_dh_params{dh_p = P, dh_g = G, dh_y = ServerPublicDh server_master_secret(#server_ecdh_params{curve = ECCurve, public = ECServerPubKey}, State) -> - %% Generate Client ECDH Key - ECClntKey = crypto:ec_key_new(ECCurve), - crypto:ec_key_generate(ECClntKey), - State1 = State#state{diffie_hellman_keys = {'ECKey', ECClntKey}}, - - ec_dh_master_secret(ECClntKey, ECServerPubKey, State1); + Key = public_key:generate_key({curve, ECCurve}), + ec_dh_master_secret(Key, #'ECPoint'{point = ECServerPubKey}, State#state{diffie_hellman_keys = Key}); server_master_secret(#server_psk_params{ hint = IdentityHint}, @@ -2126,18 +2089,18 @@ dh_master_secret(Prime, Base, PublicDhKey, undefined, State) -> PMpint = mpint_binary(Prime), GMpint = mpint_binary(Base), Keys = {_, PrivateDhKey} = - crypto:dh_generate_key([PMpint,GMpint]), + public_key:generate_key({dh, PMpint,GMpint}), dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys}); dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State) -> PremasterSecret = - crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey, - [PMpint, GMpint]), + public_key:compute_key(mpint_binary(PublicDhKey), PrivateDhKey, + {dh, PMpint, GMpint}), master_from_premaster_secret(PremasterSecret, State). ec_dh_master_secret(ECKey, ECPoint, State) -> PremasterSecret = - crypto:ecdh_compute_key(ECKey, ECPoint), + public_key:compute_key(ECPoint, ECKey), master_from_premaster_secret(PremasterSecret, State). handle_psk_identity(_PSKIdentity, LookupFun) @@ -2163,7 +2126,7 @@ dhe_psk_master_secret(PSKIdentity, Prime, Base, PublicDhKey, undefined, State) - PMpint = mpint_binary(Prime), GMpint = mpint_binary(Base), Keys = {_, PrivateDhKey} = - crypto:dh_generate_key([PMpint,GMpint]), + public_key:generate_key({dh, PMpint, GMpint}), dhe_psk_master_secret(PSKIdentity, PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys}); @@ -2172,8 +2135,8 @@ dhe_psk_master_secret(PSKIdentity, PMpint, GMpint, PublicDhKey, PrivateDhKey, case handle_psk_identity(PSKIdentity, SslOpts#ssl_options.user_lookup_fun) of {ok, PSK} when is_binary(PSK) -> DHSecret = - crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey, - [PMpint, GMpint]), + public_key:compute_key(mpint_binary(PublicDhKey), PrivateDhKey, + {dh, PMpint, GMpint}), DHLen = erlang:byte_size(DHSecret), Len = erlang:byte_size(PSK), PremasterSecret = <<?UINT16(DHLen), DHSecret/binary, ?UINT16(Len), PSK/binary>>, @@ -2202,7 +2165,7 @@ generate_srp_server_keys(_SrpParams, 10) -> generate_srp_server_keys(SrpParams = #srp_user{generator = Generator, prime = Prime, verifier = Verifier}, N) -> - case crypto:srp_generate_key(Verifier, Generator, Prime, '6a') of + case public_key:generate_key({srp, '6a', Verifier, Generator, Prime}) of error -> generate_srp_server_keys(SrpParams, N+1); Keys -> @@ -2213,7 +2176,7 @@ generate_srp_client_keys(_Generator, _Prime, 10) -> ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER); generate_srp_client_keys(Generator, Prime, N) -> - case crypto:srp_generate_key(Generator, Prime, '6a') of + case public_key:generate_key({srp, '6a', Generator, Prime}) of error -> generate_srp_client_keys(Generator, Prime, N+1); Keys -> @@ -2234,8 +2197,8 @@ handle_srp_identity(Username, {Fun, UserState}) -> throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)) end. -server_srp_master_secret(Verifier, Prime, ClientPub, State = #state{srp_keys = {ServerPub, ServerPriv}}) -> - case crypto:srp_compute_key(Verifier, Prime, ClientPub, ServerPub, ServerPriv, '6a') of +server_srp_master_secret(Verifier, Prime, ClientPub, State = #state{srp_keys = ServerKey}) -> + case public_key:compute_key(ClientPub, ServerKey, {srp, '6a', Verifier, Prime}) of error -> ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER); PremasterSecret -> @@ -2248,14 +2211,13 @@ client_srp_master_secret(Generator, Prime, Salt, ServerPub, undefined, State) -> Keys = generate_srp_client_keys(Generator, Prime, 0), client_srp_master_secret(Generator, Prime, Salt, ServerPub, Keys, State#state{srp_keys = Keys}); -client_srp_master_secret(Generator, Prime, Salt, ServerPub, {ClientPub, ClientPriv}, +client_srp_master_secret(Generator, Prime, Salt, ServerPub, ClientKeys, #state{ssl_options = SslOpts} = State) -> case ssl_srp_primes:check_srp_params(Generator, Prime) of ok -> {Username, Password} = SslOpts#ssl_options.srp_identity, - DerivedKey = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - - case crypto:srp_compute_key(DerivedKey, Prime, Generator, ClientPub, ClientPriv, ServerPub, '6a') of + case public_key:compute_key(ServerPub, ClientKeys, {srp, Username, Password, Salt, + '6a', Prime, Generator}) of error -> ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER); PremasterSecret -> @@ -3122,3 +3084,7 @@ handle_close_alert(Data, StateName, State0) -> _ -> ok end. + +default_curve(_) -> + %%TODO: select prefered curve from extension + secp256k1. diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index eca36ba650..f736de3327 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -418,8 +418,7 @@ key_exchange(client, _Version, {dh, <<?UINT32(Len), PublicKey:Len/binary>>}) -> dh_public = PublicKey} }; -key_exchange(client, _Version, {ecdh, {'ECKey', ECDHKey}}) -> - {_, _, ECPublicKey} = crypto:ec_key_to_term(ECDHKey), +key_exchange(client, _Version, {ecdh, {_,_,ECPublicKey}}) -> #client_key_exchange{ exchange_keys = #client_ec_diffie_hellman_public{ dh_public = ECPublicKey} @@ -453,8 +452,8 @@ key_exchange(client, _Version, {srp, PublicKey}) -> }; key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _}, - #'DHParameter'{prime = P, base = G}, - HashSign, ClientRandom, ServerRandom, PrivateKey}) -> + #'DHParameter'{prime = P, base = G}, + HashSign, ClientRandom, ServerRandom, PrivateKey}) -> <<?UINT32(_), PBin/binary>> = crypto:mpint(P), <<?UINT32(_), GBin/binary>> = crypto:mpint(G), ServerDHParams = #server_dh_params{dh_p = PBin, @@ -462,10 +461,9 @@ key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _}, enc_server_key_exchange(Version, ServerDHParams, HashSign, ClientRandom, ServerRandom, PrivateKey); -key_exchange(server, Version, {ecdh, {'ECKey', ECKey}, HashSign, ClientRandom, ServerRandom, - PrivateKey}) -> - {ECCurve, _ECPrivKey, ECPubKey} = crypto:ec_key_to_term(ECKey), - ServerECParams = #server_ecdh_params{curve = ECCurve, public = ECPubKey}, +key_exchange(server, Version, {ecdh, {ECCurve, _, ECPublicKey}, HashSign, ClientRandom, ServerRandom, + PrivateKey}) -> + ServerECParams = #server_ecdh_params{curve = ECCurve, public = ECPublicKey}, enc_server_key_exchange(Version, ServerECParams, HashSign, ClientRandom, ServerRandom, PrivateKey); @@ -1700,7 +1698,7 @@ digitally_signed(_Version, Hash, HashAlgo, #'DSAPrivateKey'{} = Key) -> digitally_signed(_Version, Hash, _HashAlgo, #'RSAPrivateKey'{} = Key) -> public_key:encrypt_private(Hash, Key, [{rsa_pad, rsa_pkcs1_padding}]); -digitally_signed(_Version, Hash, HashAlgo, {'ECKey', _} = Key) -> +digitally_signed(_Version, Hash, HashAlgo, Key) -> public_key:sign({digest, Hash}, HashAlgo, Key). calc_master_secret({3,0}, _PrfAlgo, PremasterSecret, ClientRandom, ServerRandom) -> |