aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/ssl_handshake.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/ssl_handshake.erl')
-rw-r--r--lib/ssl/src/ssl_handshake.erl49
1 files changed, 44 insertions, 5 deletions
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 560d5a3aaf..e74361993d 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -192,6 +192,7 @@ certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
{ecdh, #'ECPrivateKey'{}} |
{psk, binary()} |
{dhe_psk, binary(), binary()} |
+ {ecdhe_psk, binary(), #'ECPrivateKey'{}} |
{srp, {binary(), binary()}, #srp_user{}, {HashAlgo::atom(), SignAlgo::atom()},
binary(), binary(), public_key:private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
@@ -229,6 +230,13 @@ key_exchange(client, _Version, {dhe_psk, Identity, PublicKey}) ->
dh_public = PublicKey}
};
+key_exchange(client, _Version, {ecdhe_psk, Identity, #'ECPrivateKey'{publicKey = ECPublicKey}}) ->
+ #client_key_exchange{
+ exchange_keys = #client_ecdhe_psk_identity{
+ identity = Identity,
+ dh_public = ECPublicKey}
+ };
+
key_exchange(client, _Version, {psk_premaster_secret, PskIdentity, Secret, {_, PublicKey, _}}) ->
EncPremasterSecret =
encrypted_premaster_secret(Secret, PublicKey),
@@ -275,6 +283,16 @@ key_exchange(server, Version, {dhe_psk, PskIdentityHint, {PublicKey, _},
enc_server_key_exchange(Version, ServerEDHPSKParams,
HashSign, ClientRandom, ServerRandom, PrivateKey);
+key_exchange(server, Version, {ecdhe_psk, PskIdentityHint,
+ #'ECPrivateKey'{publicKey = ECPublicKey,
+ parameters = ECCurve},
+ HashSign, ClientRandom, ServerRandom, PrivateKey}) ->
+ ServerECDHEPSKParams = #server_ecdhe_psk_params{
+ hint = PskIdentityHint,
+ dh_params = #server_ecdh_params{curve = ECCurve, public = ECPublicKey}},
+ enc_server_key_exchange(Version, ServerECDHEPSKParams, HashSign,
+ ClientRandom, ServerRandom, PrivateKey);
+
key_exchange(server, Version, {srp, {PublicKey, _},
#srp_user{generator = Generator, prime = Prime,
salt = Salt},
@@ -732,6 +750,7 @@ decode_server_key(ServerKey, Type, Version) ->
| #client_ec_diffie_hellman_public{}
| #client_psk_identity{}
| #client_dhe_psk_identity{}
+ | #client_ecdhe_psk_identity{}
| #client_rsa_psk_identity{}
| #client_srp_public{}.
%%
@@ -1131,7 +1150,6 @@ select_hashsign_algs(undefined, ?rsaEncryption, _) ->
select_hashsign_algs(undefined, ?'id-dsa', _) ->
{sha, dsa}.
-
srp_user(#ssl_options{srp_identity = {UserName, _}}) ->
#srp{username = UserName};
srp_user(_) ->
@@ -1154,24 +1172,20 @@ certificate_types(_, {N, M}) when N >= 3 andalso M >= 3 ->
false ->
<<?BYTE(?RSA_SIGN), ?BYTE(?DSS_SIGN)>>
end;
-
certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == rsa;
KeyExchange == dh_rsa;
KeyExchange == dhe_rsa;
KeyExchange == ecdhe_rsa ->
<<?BYTE(?RSA_SIGN)>>;
-
certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dh_dss;
KeyExchange == dhe_dss;
KeyExchange == srp_dss ->
<<?BYTE(?DSS_SIGN)>>;
-
certificate_types({KeyExchange, _, _, _}, _) when KeyExchange == dh_ecdsa;
KeyExchange == dhe_ecdsa;
KeyExchange == ecdh_ecdsa;
KeyExchange == ecdhe_ecdsa ->
<<?BYTE(?ECDSA_SIGN)>>;
-
certificate_types(_, _) ->
<<?BYTE(?RSA_SIGN)>>.
@@ -1569,6 +1583,18 @@ encode_server_key(#server_dhe_psk_params{
YLen = byte_size(Y),
<<?UINT16(Len), PskIdentityHint/binary,
?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>;
+encode_server_key(Params = #server_ecdhe_psk_params{hint = undefined}) ->
+ encode_server_key(Params#server_ecdhe_psk_params{hint = <<>>});
+encode_server_key(#server_ecdhe_psk_params{
+ hint = PskIdentityHint,
+ dh_params = #server_ecdh_params{
+ curve = {namedCurve, ECCurve}, public = ECPubKey}}) ->
+ %%TODO: support arbitrary keys
+ Len = byte_size(PskIdentityHint),
+ KLen = size(ECPubKey),
+ <<?UINT16(Len), PskIdentityHint/binary,
+ ?BYTE(?NAMED_CURVE), ?UINT16((tls_v1:oid_to_enum(ECCurve))),
+ ?BYTE(KLen), ECPubKey/binary>>;
encode_server_key(#server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B}) ->
NLen = byte_size(N),
GLen = byte_size(G),
@@ -1601,6 +1627,12 @@ encode_client_key(#client_dhe_psk_identity{identity = Id, dh_public = DHPublic},
Len = byte_size(Id),
DHLen = byte_size(DHPublic),
<<?UINT16(Len), Id/binary, ?UINT16(DHLen), DHPublic/binary>>;
+encode_client_key(Identity = #client_ecdhe_psk_identity{identity = undefined}, Version) ->
+ encode_client_key(Identity#client_ecdhe_psk_identity{identity = <<"psk_identity">>}, Version);
+encode_client_key(#client_ecdhe_psk_identity{identity = Id, dh_public = DHPublic}, _) ->
+ Len = byte_size(Id),
+ DHLen = byte_size(DHPublic),
+ <<?UINT16(Len), Id/binary, ?BYTE(DHLen), DHPublic/binary>>;
encode_client_key(Identity = #client_rsa_psk_identity{identity = undefined}, Version) ->
encode_client_key(Identity#client_rsa_psk_identity{identity = <<"psk_identity">>}, Version);
encode_client_key(#client_rsa_psk_identity{identity = Id, exchange_keys = ExchangeKeys}, Version) ->
@@ -1756,6 +1788,10 @@ dec_client_key(<<?UINT16(Len), Id:Len/binary,
?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>,
?KEY_EXCHANGE_DHE_PSK, _) ->
#client_dhe_psk_identity{identity = Id, dh_public = DH_Y};
+dec_client_key(<<?UINT16(Len), Id:Len/binary,
+ ?BYTE(DH_YLen), DH_Y:DH_YLen/binary>>,
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK, _) ->
+ #client_ecdhe_psk_identity{identity = Id, dh_public = DH_Y};
dec_client_key(<<?UINT16(Len), Id:Len/binary, PKEPMS/binary>>,
?KEY_EXCHANGE_RSA_PSK, {3, 0}) ->
#client_rsa_psk_identity{identity = Id,
@@ -1939,6 +1975,8 @@ key_exchange_alg(psk) ->
?KEY_EXCHANGE_PSK;
key_exchange_alg(dhe_psk) ->
?KEY_EXCHANGE_DHE_PSK;
+key_exchange_alg(ecdhe_psk) ->
+ ?KEY_EXCHANGE_EC_DIFFIE_HELLMAN_PSK;
key_exchange_alg(rsa_psk) ->
?KEY_EXCHANGE_RSA_PSK;
key_exchange_alg(Alg)
@@ -2167,6 +2205,7 @@ is_acceptable_hash_sign({_, ecdsa} = Algos, ecdsa, ecdsa, ecdhe_ecdsa, Supported
is_acceptable_hash_sign(_, _, _, KeyExAlgo, _) when
KeyExAlgo == psk;
KeyExAlgo == dhe_psk;
+ KeyExAlgo == ecdhe_psk;
KeyExAlgo == srp_anon;
KeyExAlgo == dh_anon;
KeyExAlgo == ecdhe_anon