aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-04-17 10:28:25 +0200
committerIngela Anderton Andin <[email protected]>2013-05-08 10:39:18 +0200
commitdfd9c13f882ef199dfcb830823cb12d83bcc4f10 (patch)
treedc99edce4ec3f01f1ab40cd1dde2256637e82ded /lib
parentd565a551ff2605c8abca0009ab90fbb7687a4097 (diff)
downloadotp-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')
-rw-r--r--lib/public_key/src/public_key.erl192
-rw-r--r--lib/ssl/src/ssl_connection.erl104
-rw-r--r--lib/ssl/src/ssl_handshake.erl16
3 files changed, 171 insertions, 141 deletions
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 4b8fda8d40..41ebaef76d 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -34,7 +34,8 @@
decrypt_private/2, decrypt_private/3,
encrypt_public/2, encrypt_public/3,
decrypt_public/2, decrypt_public/3,
- sign/3, verify/4,
+ sign/3, verify/4, generate_key/1, generate_key/2,
+ compute_key/2, compute_key/3,
pkix_sign/2, pkix_verify/2,
pkix_sign_types/1,
pkix_is_self_signed/1,
@@ -323,58 +324,70 @@ encrypt_private(PlainText,
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
crypto:rsa_private_encrypt(PlainText, format_rsa_private_key(Key), Padding).
-format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D,
- prime1 = P1, prime2 = P2,
- exponent1 = E1, exponent2 = E2,
- coefficient = C})
- when is_integer(N), is_integer(E), is_integer(D),
- is_integer(P1), is_integer(P2),
- is_integer(E1), is_integer(E2), is_integer(C) ->
- [E, N, D, P1, P2, E1, E2, C];
-
-format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
- privateExponent = D}) when is_integer(N),
- is_integer(E),
- is_integer(D) ->
- [E, N, D].
+%%--------------------------------------------------------------------
+-spec generate_key(#'ECPrivateKey'{} | {curve, Name ::atom()} | #'DHParameter'{}) -> {'ECKey', term()} | {binary(), binary()}.
+-spec generate_key(#'ECPoint'{}, #'OTPECParameters'{} | {namedCurve, oid()}) -> {'ECKey', term()}.
-%%
-%% Description: convert a ECPrivate key into resource Key
+%% Description: Generates new key(s)
%%--------------------------------------------------------------------
-list2int(L) ->
- S = length(L) * 8,
- <<R:S/integer>> = erlang:iolist_to_binary(L),
- R.
+generate_key(#'ECPrivateKey'{} = Key) ->
+ ec_private_key_to_eckey(Key);
-ec_private_key_to_eckey(#'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)}.
+generate_key({curve, Name}) ->
+ %% TODO: Better crypto API
+ ECDHKey = crypto:ec_key_new(Name),
+ crypto:ec_key_generate(ECDHKey),
+ crypto:ec_key_to_term(ECDHKey);
-ec_public_key_to_eckey({#'ECPoint'{point = ECPoint}, Param}) ->
- 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, undefined, ECPoint},
- {'ECKey', crypto:term_to_ec_key(Key)}.
+generate_key(#'DHParameter'{prime = P, base = G}) ->
+ crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]);
+
+generate_key({dh, Prime, Base}) when is_binary(Prime), is_binary(Base) ->
+ %% TODO: Is mpint could be normal binary!
+ crypto:dh_generate_key([Prime, Base]);
+
+generate_key({srp, Version, Generator, Prime}) when is_binary(Generator), is_binary(Prime) ->
+ crypto:srp_generate_key(Generator, Prime, Version);
+
+generate_key({srp, Version, Verifier, Generator, Prime}) when is_binary(Verifier), is_binary(Generator), is_binary(Prime) ->
+ crypto:srp_generate_key(Verifier, Generator, Prime, Version).
+
+generate_key(#'ECPoint'{} = Key, Params) ->
+ %% TODO: Better crypto API
+ ECKey = ec_public_key_to_eckey({Key,Params}),
+ ECClntKey = crypto:term_to_ec_key(ECKey),
+ crypto:ec_key_generate(ECClntKey),
+ crypto:ec_key_to_term(ECClntKey).
%%--------------------------------------------------------------------
+-spec compute_key(#'ECPoint'{}, {'ECKey', binary()}) -> binary().
+-spec compute_key(OthersKey ::binary(), MyKey::binary() | {binary(), binary()},
+ {dh, binary(), binary()} |
+ {srp, atom(), binary(), binary()} |
+ {srp, string(), string(), binary(), atom(), binary(), binary()})
+ -> binary().
+%% Description: Compute shared secret
+%%--------------------------------------------------------------------
+compute_key(#'ECPoint'{point = Point}, Term) ->
+ %% TODO: Better crypto API
+ ECKey = crypto:term_to_ec_key(Term),
+ crypto:ecdh_compute_key(ECKey, Point).
+
+compute_key(OthersKey, MyKey, {dh, Prime, Base}) when is_binary(OthersKey),
+ is_binary(MyKey),
+ is_binary(Prime),
+ is_binary(Base) ->
+ %% TODO: Is mpint could be binary!
+ crypto:dh_compute_key(OthersKey, MyKey, [Prime, Base]);
+
+compute_key(ClientPub, {ServerPub, ServerPriv}, {srp, Version, Verifier, Prime}) ->
+ crypto:srp_compute_key(Verifier, Prime, ClientPub, ServerPub, ServerPriv, Version);
+
+compute_key(ServerPub, {ClientPub, ClientPriv}, {srp, Username, Password, Salt, Version, Prime, Generator}) ->
+ DerivedKey = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]),
+ crypto:srp_compute_key(DerivedKey, Prime, Generator, ClientPub, ClientPriv, ServerPub, Version).
+%%--------------------------------------------------------------------
-spec pkix_sign_types(SignatureAlg::oid()) ->
%% Relevant dsa digest type is subpart of rsa digest type
{ DigestType :: rsa_digest_type(),
@@ -430,14 +443,15 @@ sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) ->
sign(Digest, DigestType, Key = {?'id-ecPublicKey', _, _}) ->
sign(Digest, DigestType, ec_public_key_to_eckey(Key));
-sign(Digest, DigestType, Key = #'ECPrivateKey'{}) ->
- sign(Digest, DigestType, ec_private_key_to_eckey(Key));
-
-sign({digest,_}=Digest, DigestType, {'ECKey', Key}) ->
- crypto:sign(ecdsa, DigestType, Digest, Key);
+sign({digest,_} = Digest, DigestType, Key = #'ECPrivateKey'{}) ->
+ ECDHKey = ec_private_key_to_eckey(Key),
+ ECKey = crypto:term_to_ec_key(ECDHKey),
+ crypto:sign(ecdsa, DigestType, Digest, ECKey);
-sign(PlainText, DigestType, {'ECKey', Key}) ->
- crypto:sign(ecdsa, DigestType, PlainText, Key);
+sign(PlainText, DigestType, Key = #'ECPrivateKey'{}) ->
+ ECDHKey = ec_private_key_to_eckey(Key),
+ ECKey = crypto:term_to_ec_key(ECDHKey),
+ crypto:sign(ecdsa, DigestType, PlainText, ECKey);
%% Backwards compatible
sign(Digest, none, #'DSAPrivateKey'{} = Key) ->
@@ -462,17 +476,15 @@ verify({digest,_} = Digest, sha = DigestType, Signature, {Key, #'Dss-Parms'{p =
when is_integer(Key), is_binary(Signature) ->
crypto:verify(dss, DigestType, Digest, Signature, [P, Q, G, Key]);
-verify({digest,_} = Digest, DigestType, Signature, {'ECKey', Key}) ->
- crypto:verify(ecdsa, DigestType, Digest, Signature, Key);
-
-verify(PlainText, DigestType, Signature, Key = #'ECPrivateKey'{}) ->
- verify(PlainText, DigestType, Signature, ec_private_key_to_eckey(Key));
+verify(Digest, DigestType, Signature, Key = #'ECPrivateKey'{}) ->
+ ECDHKey = ec_private_key_to_eckey(Key),
+ ECKey = crypto:term_to_ec_key(ECDHKey),
+ crypto:verify(ecdsa, DigestType, Digest, Signature, ECKey);
-verify(PlainText, DigestType, Signature, Key = {#'ECPoint'{}, _}) ->
- verify(PlainText, DigestType, Signature, ec_public_key_to_eckey(Key));
-
-verify(PlainText, DigestType, Signature, {'ECKey', Key}) ->
- crypto:verify(ecdsa, DigestType, PlainText, Signature, Key);
+verify(Digest, DigestType, Signature, Key = {#'ECPoint'{}, _}) ->
+ ECDHKey = ec_public_key_to_eckey(Key),
+ ECKey = crypto:term_to_ec_key(ECDHKey),
+ crypto:verify(ecdsa, DigestType, Digest, Signature, ECKey);
%% Backwards compatibility
verify(Digest, none, Signature, {_, #'Dss-Parms'{}} = Key ) ->
@@ -910,3 +922,57 @@ combine(CRL, DeltaCRLs) ->
end,
lists:foldl(Fun, hd(Deltas), tl(Deltas))
end.
+
+format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D,
+ prime1 = P1, prime2 = P2,
+ exponent1 = E1, exponent2 = E2,
+ coefficient = C})
+ when is_integer(N), is_integer(E), is_integer(D),
+ is_integer(P1), is_integer(P2),
+ is_integer(E1), is_integer(E2), is_integer(C) ->
+ [E, N, D, P1, P2, E1, E2, C];
+
+format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D}) when is_integer(N),
+ is_integer(E),
+ is_integer(D) ->
+ [E, N, D].
+
+%%
+%% Description: convert a ECPrivate key into resource Key
+%%--------------------------------------------------------------------
+list2int(L) ->
+ S = length(L) * 8,
+ <<R:S/integer>> = erlang:iolist_to_binary(L),
+ R.
+
+ec_private_key_to_eckey(#'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,
+ {ECCurve, list2int(PrivKey), undefined}.
+ %%{'ECKey', crypto:term_to_ec_key(Key)}.
+
+ec_public_key_to_eckey({#'ECPoint'{point = ECPoint}, Param}) ->
+ 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,
+ {ECCurve, undefined, ECPoint}.
+ %%{'ECKey', crypto:term_to_ec_key(Key)}.
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) ->