aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/Makefile3
-rw-r--r--lib/ssl/src/ssl.app.src1
-rw-r--r--lib/ssl/src/ssl.erl13
-rw-r--r--lib/ssl/src/ssl_cipher.erl114
-rw-r--r--lib/ssl/src/ssl_cipher.hrl29
-rw-r--r--lib/ssl/src/ssl_connection.erl167
-rw-r--r--lib/ssl/src/ssl_handshake.erl100
-rw-r--r--lib/ssl/src/ssl_handshake.hrl23
-rw-r--r--lib/ssl/src/ssl_internal.hrl1
-rw-r--r--lib/ssl/src/ssl_srp.hrl31
-rw-r--r--lib/ssl/src/ssl_srp_primes.erl506
-rw-r--r--lib/ssl/src/ssl_srp_primes.hrl1
12 files changed, 964 insertions, 25 deletions
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index e61f415c84..d3ba76d34e 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -50,6 +50,7 @@ MODULES= \
ssl_certificate\
ssl_certificate_db\
ssl_cipher \
+ ssl_srp_primes \
ssl_connection \
ssl_connection_sup \
ssl_handshake \
@@ -65,7 +66,7 @@ MODULES= \
INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_internal.hrl \
- ssl_record.hrl
+ ssl_record.hrl ssl_srp.hrl ssl_srp_primes.hrl
ERL_FILES= \
$(MODULES:%=%.erl) \
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index 897a097f73..5c34de905e 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -20,6 +20,7 @@
ssl_connection_sup,
ssl_connection,
ssl_cipher,
+ ssl_srp_primes,
ssl_certificate_db,
ssl_certificate,
ssl_alert
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0381f81edd..d5f5fa6b04 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -37,6 +37,7 @@
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
-include("ssl_handshake.hrl").
+-include("ssl_srp_primes.hrl").
-include_lib("public_key/include/public_key.hrl").
@@ -67,6 +68,7 @@
{cacertfile, path()} | {dh, Der::binary()} | {dhfile, path()} |
{user_lookup_fun, {fun(), InitialUserState::term()}} |
{psk_identity, string()} |
+ {srp_identity, {string(), string()}} |
{ciphers, ciphers()} | {ssl_imp, ssl_imp()} | {reuse_sessions, boolean()} |
{reuse_session, fun()} | {hibernate_after, integer()|undefined} |
{next_protocols_advertised, list(binary())} |
@@ -639,6 +641,7 @@ handle_options(Opts0, _Role) ->
dhfile = handle_option(dhfile, Opts, undefined),
user_lookup_fun = handle_option(user_lookup_fun, Opts, undefined),
psk_identity = handle_option(psk_identity, Opts, undefined),
+ srp_identity = handle_option(srp_identity, Opts, undefined),
ciphers = handle_option(ciphers, Opts, []),
%% Server side option
reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
@@ -659,7 +662,7 @@ handle_options(Opts0, _Role) ->
fail_if_no_peer_cert, verify_client_once,
depth, cert, certfile, key, keyfile,
password, cacerts, cacertfile, dh, dhfile,
- user_lookup_fun, psk_identity, ciphers,
+ user_lookup_fun, psk_identity, srp_identity, ciphers,
reuse_session, reuse_sessions, ssl_imp,
cb_info, renegotiate_at, secure_renegotiate, hibernate_after,
erl_dist, next_protocols_advertised,
@@ -770,6 +773,11 @@ validate_option(user_lookup_fun, undefined) ->
undefined;
validate_option(user_lookup_fun, {Fun, _} = Value) when is_function(Fun, 3) ->
Value;
+validate_option(srp_identity, undefined) ->
+ undefined;
+validate_option(srp_identity, {Username, Password})
+ when is_list(Username), is_list(Password), Username =/= "", length(Username) =< 255 ->
+ {list_to_binary(Username), list_to_binary(Password)};
validate_option(ciphers, Value) when is_list(Value) ->
Version = ssl_record:highest_protocol_version([]),
try cipher_suites(Version, Value)
@@ -942,7 +950,8 @@ cipher_suites(Version, [{_,_,_}| _] = Ciphers0) ->
cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
Supported = ssl_cipher:suites(Version)
++ ssl_cipher:anonymous_suites()
- ++ ssl_cipher:psk_suites(Version),
+ ++ ssl_cipher:psk_suites(Version)
+ ++ ssl_cipher:srp_suites(),
case [Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported)] of
[] ->
Supported;
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 0bdcfd236d..be629dcdd1 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -34,7 +34,7 @@
-export([security_parameters/3, suite_definition/1,
decipher/5, cipher/5,
- suite/1, suites/1, anonymous_suites/0, psk_suites/1,
+ suite/1, suites/1, anonymous_suites/0, psk_suites/1, srp_suites/0,
openssl_suite/1, openssl_suite_name/1, filter/2,
hash_algorithm/1, sign_algorithm/1]).
@@ -248,6 +248,23 @@ psk_suites(_) ->
?TLS_PSK_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
+-spec srp_suites() -> [cipher_suite()].
+%%
+%% Description: Returns a list of the SRP cipher suites, only supported
+%% if explicitly set by user.
+%%--------------------------------------------------------------------
+srp_suites() ->
+ [?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
+
+%%--------------------------------------------------------------------
-spec suite_definition(cipher_suite()) -> int_cipher_suite().
%%
%% Description: Return erlang cipher suite definition.
@@ -385,7 +402,29 @@ suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
{rsa_psk, null, sha256, default_prf};
suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
- {rsa_psk, null, sha384, default_prf}.
+ {rsa_psk, null, sha384, default_prf};
+
+%%% SRP Cipher Suites RFC 5054
+
+suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
+ {srp_anon, '3des_ede_cbc', sha, default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ {srp_rsa, '3des_ede_cbc', sha, default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ {srp_dss, '3des_ede_cbc', sha, default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
+ {srp_anon, aes_128_cbc, sha, default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ {srp_rsa, aes_128_cbc, sha, default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ {srp_dss, aes_128_cbc, sha, default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
+ {srp_anon, aes_256_cbc, sha, default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ {srp_rsa, aes_256_cbc, sha, default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ {srp_dss, aes_256_cbc, sha, default_prf}.
+
%%--------------------------------------------------------------------
-spec suite(erl_cipher_suite()) -> cipher_suite().
@@ -513,7 +552,28 @@ suite({dhe_psk, null, sha384}) ->
suite({rsa_psk, null, sha256}) ->
?TLS_RSA_PSK_WITH_NULL_SHA256;
suite({rsa_psk, null, sha384}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA384.
+ ?TLS_RSA_PSK_WITH_NULL_SHA384;
+
+%%% SRP Cipher Suites RFC 5054
+
+suite({srp_anon, '3des_ede_cbc', sha}) ->
+ ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+suite({srp_rsa, '3des_ede_cbc', sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+suite({srp_dss, '3des_ede_cbc', sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+suite({srp_anon, aes_128_cbc, sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+suite({srp_rsa, aes_128_cbc, sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+suite({srp_dss, aes_128_cbc, sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+suite({srp_anon, aes_256_cbc, sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+suite({srp_rsa, aes_256_cbc, sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+suite({srp_dss, aes_256_cbc, sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA.
%%--------------------------------------------------------------------
-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
@@ -558,7 +618,24 @@ openssl_suite("RC4-MD5") ->
openssl_suite("EDH-RSA-DES-CBC-SHA") ->
?TLS_DHE_RSA_WITH_DES_CBC_SHA;
openssl_suite("DES-CBC-SHA") ->
- ?TLS_RSA_WITH_DES_CBC_SHA.
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA.
+
+
%%--------------------------------------------------------------------
-spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite().
%%
@@ -624,6 +701,21 @@ openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
"PSK-RC4-SHA";
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-RSA-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-DSS-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ "SRP-RSA-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ "SRP-DSS-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ "SRP-RSA-AES-256-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ "SRP-DSS-AES-256-CBC-SHA";
+
%% No oppenssl name
openssl_suite_name(Cipher) ->
suite_definition(Cipher).
@@ -858,7 +950,7 @@ next_iv(Bin, IV) ->
rsa_signed_suites() ->
dhe_rsa_suites() ++ rsa_suites() ++
- psk_rsa_suites().
+ psk_rsa_suites() ++ srp_rsa_suites().
dhe_rsa_suites() ->
[?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
@@ -876,6 +968,11 @@ psk_rsa_suites() ->
?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
?TLS_RSA_PSK_WITH_RC4_128_SHA].
+srp_rsa_suites() ->
+ [?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA].
+
rsa_suites() ->
[?TLS_RSA_WITH_AES_256_CBC_SHA256,
?TLS_RSA_WITH_AES_256_CBC_SHA,
@@ -887,7 +984,7 @@ rsa_suites() ->
?TLS_RSA_WITH_DES_CBC_SHA].
dsa_signed_suites() ->
- dhe_dss_suites().
+ dhe_dss_suites() ++ srp_dss_suites().
dhe_dss_suites() ->
[?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
@@ -897,6 +994,11 @@ dhe_dss_suites() ->
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA].
+srp_dss_suites() ->
+ [?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
+
filter_rsa(OtpCert, RsaCiphers) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
TBSExtensions = TBSCert#'OTPTBSCertificate'.extensions,
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index db6e36741d..90d3704efd 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -326,4 +326,33 @@
%% TLS_RSA_PSK_WITH_NULL_SHA384 = {0x00,0xB9};
-define(TLS_RSA_PSK_WITH_NULL_SHA384, <<?BYTE(16#00), ?BYTE(16#B9)>>).
+%%% SRP Cipher Suites RFC 5054
+
+%% TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = { 0xC0,0x1A };
+-define(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1A)>>).
+
+%% TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = { 0xC0,0x1B };
+-define(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1B)>>).
+
+%% TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = { 0xC0,0x1C };
+-define(TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1C)>>).
+
+%% TLS_SRP_SHA_WITH_AES_128_CBC_SHA = { 0xC0,0x1D };
+-define(TLS_SRP_SHA_WITH_AES_128_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1D)>>).
+
+%% TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = { 0xC0,0x1E };
+-define(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1E)>>).
+
+%% TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = { 0xC0,0x1F };
+-define(TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#1F)>>).
+
+%% TLS_SRP_SHA_WITH_AES_256_CBC_SHA = { 0xC0,0x20 };
+-define(TLS_SRP_SHA_WITH_AES_256_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#20)>>).
+
+%% TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = { 0xC0,0x21 };
+-define(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#21)>>).
+
+%% TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = { 0xC0,0x22 };
+-define(TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, <<?BYTE(16#C0), ?BYTE(16#22)>>).
+
-endif. % -ifdef(ssl_cipher).
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index e3ddce85e1..e752b70d18 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -34,6 +34,8 @@
-include("ssl_record.hrl").
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
+-include("ssl_srp.hrl").
+-include("ssl_srp_primes.hrl").
-include_lib("public_key/include/public_key.hrl").
%% Internal application API
@@ -81,6 +83,8 @@
diffie_hellman_params, % PKIX: #'DHParameter'{} relevant for server side
diffie_hellman_keys, % {PublicKey, PrivateKey}
psk_identity, % binary() - server psk identity hint
+ srp_params, % #srp_user{}
+ srp_keys, % {PublicKey, PrivateKey}
premaster_secret, %
file_ref_db, % ets()
cert_db_ref, % ref()
@@ -530,7 +534,8 @@ certify(#server_key_exchange{} = KeyExchangeMsg,
#state{role = client, negotiated_version = Version,
key_algorithm = Alg} = State0)
when Alg == dhe_dss; Alg == dhe_rsa; Alg == dh_anon;
- Alg == psk; Alg == dhe_psk; Alg == rsa_psk ->
+ Alg == psk; Alg == dhe_psk; Alg == rsa_psk;
+ Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon ->
case handle_server_key(KeyExchangeMsg, State0) of
#state{} = State1 ->
{Record, State} = next_record(State1),
@@ -712,6 +717,20 @@ certify_client_key_exchange(#client_rsa_psk_identity{
next_state(certify, cipher, Record, State);
#alert{} = Alert ->
handle_own_alert(Alert, Version, certify, State0)
+ end;
+
+certify_client_key_exchange(#client_srp_public{srp_a = ClientPublicKey},
+ #state{negotiated_version = Version,
+ srp_params =
+ #srp_user{prime = Prime,
+ verifier = Verifier}
+ } = State0) ->
+ case server_srp_master_secret(Verifier, Prime, ClientPublicKey, State0) of
+ #state{} = State1 ->
+ {Record, State} = next_record(State1),
+ next_state(certify, cipher, Record, State);
+ #alert{} = Alert ->
+ handle_own_alert(Alert, Version, certify, State0)
end.
%%--------------------------------------------------------------------
@@ -1667,6 +1686,44 @@ key_exchange(#state{role = server, key_algorithm = rsa_psk,
State#state{connection_states = ConnectionStates,
tls_handshake_history = Handshake};
+key_exchange(#state{role = server, key_algorithm = Algo,
+ ssl_options = #ssl_options{user_lookup_fun = LookupFun},
+ hashsign_algorithm = HashSignAlgo,
+ session = #session{srp_username = Username},
+ private_key = PrivateKey,
+ connection_states = ConnectionStates0,
+ negotiated_version = Version,
+ tls_handshake_history = Handshake0,
+ socket = Socket,
+ transport_cb = Transport
+ } = State)
+ when Algo == srp_dss;
+ Algo == srp_rsa;
+ Algo == srp_anon ->
+ SrpParams = handle_srp_identity(Username, LookupFun),
+ Keys = case generate_srp_server_keys(SrpParams, 0) of
+ Alert = #alert{} ->
+ throw(Alert);
+ Keys0 = {_,_} ->
+ Keys0
+ end,
+ 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, {srp, Keys, SrpParams,
+ HashSignAlgo, ClientRandom,
+ ServerRandom,
+ PrivateKey}),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
+ Transport:send(Socket, BinMsg),
+ State#state{connection_states = ConnectionStates,
+ srp_params = SrpParams,
+ srp_keys = Keys,
+ tls_handshake_history = Handshake};
+
key_exchange(#state{role = client,
connection_states = ConnectionStates0,
key_algorithm = rsa,
@@ -1741,6 +1798,23 @@ key_exchange(#state{role = client,
encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
Transport:send(Socket, BinMsg),
State#state{connection_states = ConnectionStates,
+ tls_handshake_history = Handshake};
+
+key_exchange(#state{role = client,
+ connection_states = ConnectionStates0,
+ key_algorithm = Algorithm,
+ negotiated_version = Version,
+ srp_keys = {ClntPubKey, _},
+ socket = Socket, transport_cb = Transport,
+ tls_handshake_history = Handshake0} = State)
+ when Algorithm == srp_dss;
+ Algorithm == srp_rsa;
+ Algorithm == srp_anon ->
+ Msg = ssl_handshake:key_exchange(client, Version, {srp, ClntPubKey}),
+ {BinMsg, ConnectionStates, Handshake} =
+ encode_handshake(Msg, Version, ConnectionStates0, Handshake0),
+ Transport:send(Socket, BinMsg),
+ State#state{connection_states = ConnectionStates,
tls_handshake_history = Handshake}.
rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
@@ -1905,7 +1979,11 @@ server_master_secret(#server_dhe_psk_params{
hint = IdentityHint,
dh_params = #server_dh_params{dh_p = P, dh_g = G, dh_y = ServerPublicDhKey}},
State) ->
- dhe_psk_master_secret(IdentityHint, P, G, ServerPublicDhKey, undefined, State).
+ dhe_psk_master_secret(IdentityHint, P, G, ServerPublicDhKey, undefined, State);
+
+server_master_secret(#server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B},
+ State) ->
+ client_srp_master_secret(G, N, S, B, undefined, State).
master_from_premaster_secret(PremasterSecret,
#state{session = Session,
@@ -1992,6 +2070,79 @@ server_rsa_psk_master_secret(PskIdentity, PremasterSecret,
?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)
end.
+generate_srp_server_keys(_SrpParams, 10) ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+generate_srp_server_keys(SrpParams =
+ #srp_user{generator = Generator, prime = Prime,
+ verifier = Verifier}, N) ->
+ Private = ssl:random_bytes(32),
+ Multiplier = crypto:srp6a_multiplier(Generator, Prime),
+ case crypto:srp_value_B(Multiplier, Verifier, Generator, Private, Prime) of
+ error ->
+ generate_srp_server_keys(SrpParams, N+1);
+ Public -> {Public, Private}
+ end.
+
+generate_srp_client_keys(_Generator, _Prime, 10) ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+generate_srp_client_keys(Generator, Prime, N) ->
+ Private = ssl:random_bytes(32),
+ case crypto:srp_mod_exp(Generator, Private, Prime) of
+ error ->
+ generate_srp_client_keys(Generator, Prime, N+1);
+ Public -> {Public, Private}
+ end.
+
+handle_srp_identity(Username, {Fun, UserState}) ->
+ case Fun(srp, Username, UserState) of
+ {ok, {SRPParams, Salt, UserPassHash}}
+ when is_atom(SRPParams), is_binary(Salt), is_binary(UserPassHash) ->
+ {Generator, Prime} = ssl_srp_primes:get_srp_params(SRPParams),
+ Verifier = crypto:srp_mod_exp(Generator, UserPassHash, Prime),
+ #srp_user{generator = Generator, prime = Prime,
+ salt = Salt, verifier = Verifier};
+ #alert{} = Alert ->
+ throw(Alert);
+ _ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
+ end.
+
+server_srp_master_secret(Verifier, Prime, ClntPub, State = #state{srp_keys = {SrvrPub, SrvrPriv}}) ->
+ U = crypto:srp6_value_u(ClntPub, SrvrPub, Prime),
+ case crypto:srp_server_secret(Verifier, SrvrPriv, U, ClntPub, Prime) of
+ error ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ PremasterSecret ->
+ master_from_premaster_secret(PremasterSecret, State)
+ end.
+
+client_srp_master_secret(_Generator, _Prime, _Salt, _SrvrPub, #alert{} = Alert, _State) ->
+ Alert;
+client_srp_master_secret(Generator, Prime, Salt, SrvrPub, undefined, State) ->
+ Keys = generate_srp_client_keys(Generator, Prime, 0),
+ client_srp_master_secret(Generator, Prime, Salt, SrvrPub, Keys, State#state{srp_keys = Keys});
+
+client_srp_master_secret(Generator, Prime, Salt, SrvrPub, {ClntPub, ClntPriv},
+ #state{ssl_options = SslOpts} = State) ->
+ case ssl_srp_primes:check_srp_params(Generator, Prime) of
+ ok ->
+ {Username, Password} = SslOpts#ssl_options.srp_identity,
+ UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]),
+
+ Multiplier = crypto:srp6a_multiplier(Generator, Prime),
+ U = crypto:srp6_value_u(ClntPub, SrvrPub, Prime),
+ case crypto:srp_client_secret(ClntPriv, U, SrvrPub, Multiplier,
+ Generator, UserPassHash, Prime) of
+ error ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
+ PremasterSecret ->
+
+ master_from_premaster_secret(PremasterSecret, State)
+ end;
+ _ ->
+ ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)
+ end.
+
cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) ->
ConnectionStates = ssl_record:set_server_verify_data(current_both, Data, ConnectionStates0),
next_state_connection(cipher, ack_connection(State#state{session = Session,
@@ -2791,22 +2942,26 @@ default_hashsign(_Version = {Major, Minor}, KeyExchange)
when Major == 3 andalso Minor >= 3 andalso
(KeyExchange == rsa orelse
KeyExchange == dhe_rsa orelse
- KeyExchange == dh_rsa) ->
+ KeyExchange == dh_rsa orelse
+ KeyExchange == srp_rsa) ->
{sha, rsa};
default_hashsign(_Version, KeyExchange)
when KeyExchange == rsa;
KeyExchange == dhe_rsa;
- KeyExchange == dh_rsa ->
+ KeyExchange == dh_rsa;
+ KeyExchange == srp_rsa ->
{md5sha, rsa};
default_hashsign(_Version, KeyExchange)
when KeyExchange == dhe_dss;
- KeyExchange == dh_dss ->
+ KeyExchange == dh_dss;
+ KeyExchange == srp_dss ->
{sha, dsa};
default_hashsign(_Version, KeyExchange)
when KeyExchange == dh_anon;
KeyExchange == psk;
KeyExchange == dhe_psk;
- KeyExchange == rsa_psk ->
+ KeyExchange == rsa_psk;
+ KeyExchange == srp_anon ->
{null, anon}.
start_or_recv_cancel_timer(infinity, _RecvFrom) ->
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index d0bf710e03..83c0092de2 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -28,6 +28,7 @@
-include("ssl_cipher.hrl").
-include("ssl_alert.hrl").
-include("ssl_internal.hrl").
+-include("ssl_srp.hrl").
-include_lib("public_key/include/public_key.hrl").
-export([master_secret/4, client_hello/8, server_hello/5, hello/4,
@@ -65,6 +66,7 @@ client_hello(Host, Port, ConnectionStates,
Pending = ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = Pending#connection_state.security_parameters,
Ciphers = available_suites(UserSuites, Version),
+ SRP = srp_user(SslOpts),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
@@ -76,6 +78,7 @@ client_hello(Host, Port, ConnectionStates,
renegotiation_info =
renegotiation_info(client, ConnectionStates, Renegotiation),
+ srp = SRP,
hash_signs = default_hash_signs(),
next_protocol_negotiation =
encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector, Renegotiation)
@@ -162,7 +165,8 @@ hello(#server_hello{cipher_suite = CipherSuite, server_version = Version,
hello(#client_hello{client_version = ClientVersion, random = Random,
cipher_suites = CipherSuites,
- renegotiation_info = Info} = Hello,
+ renegotiation_info = Info,
+ srp = SRP} = Hello,
#ssl_options{versions = Versions,
secure_renegotiate = SecureRenegotation} = SslOpts,
{Port, Session0, Cache, CacheCb, ConnectionStates0, Cert}, Renegotiation) ->
@@ -171,13 +175,14 @@ hello(#client_hello{client_version = ClientVersion, random = Random,
case ssl_record:is_acceptable_version(Version, Versions) of
true ->
{Type, #session{cipher_suite = CipherSuite,
- compression_method = Compression} = Session}
+ compression_method = Compression} = Session1}
= select_session(Hello, Port, Session0, Version,
SslOpts, Cache, CacheCb, Cert),
case CipherSuite of
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
_ ->
+ Session = handle_srp_info(SRP, Session1),
case handle_renegotiation_info(server, Info, ConnectionStates0,
Renegotiation, SecureRenegotation,
CipherSuites) of
@@ -372,8 +377,10 @@ certificate_request(ConnectionStates, CertDbHandle, CertDbRef) ->
{premaster_secret, binary(), public_key_info()} |
{dh, binary()} |
{dh, {binary(), binary()}, #'DHParameter'{}, {HashAlgo::atom(), SignAlgo::atom()},
+ binary(), binary(), private_key()} |
{psk, binary()} |
- {dhe_psk, binary(), binary()},
+ {dhe_psk, binary(), binary()} |
+ {srp, {binary(), binary()}, #srp_user{}, {HashAlgo::atom(), SignAlgo::atom()},
binary(), binary(), private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
@@ -411,6 +418,12 @@ key_exchange(client, _Version, {psk_premaster_secret, PskIdentity, Secret, {_, P
identity = PskIdentity,
exchange_keys = EncPremasterSecret}};
+key_exchange(client, _Version, {srp, PublicKey}) ->
+ #client_key_exchange{
+ exchange_keys = #client_srp_public{
+ srp_a = PublicKey}
+ };
+
key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _},
#'DHParameter'{prime = P, base = G},
HashSign, ClientRandom, ServerRandom, PrivateKey}) ->
@@ -437,7 +450,16 @@ key_exchange(server, Version, {dhe_psk, PskIdentityHint, {<<?UINT32(Len), Public
dh_params = #server_dh_params{dh_p = PBin,
dh_g = GBin, dh_y = PublicKey}
},
- enc_server_key_exchange(Version, ServerEDHPSKParams, HashSign,
+ enc_server_key_exchange(Version, ServerEDHPSKParams,
+ HashSign, ClientRandom, ServerRandom, PrivateKey);
+
+key_exchange(server, Version, {srp, {PublicKey, _},
+ #srp_user{generator = Generator, prime = Prime,
+ salt = Salt},
+ HashSign, ClientRandom, ServerRandom, PrivateKey}) ->
+ ServerSRPParams = #server_srp_params{srp_n = Prime, srp_g = Generator,
+ srp_s = Salt, srp_b = PublicKey},
+ enc_server_key_exchange(Version, ServerSRPParams, HashSign,
ClientRandom, ServerRandom, PrivateKey).
enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo},
@@ -571,7 +593,8 @@ get_tls_handshake(Version, Data, Buffer) ->
| #client_diffie_hellman_public{}
| #client_psk_identity{}
| #client_dhe_psk_identity{}
- | #client_rsa_psk_identity{}.
+ | #client_rsa_psk_identity{}
+ | #client_srp_public{}.
%%
%% Description: Decode client_key data and return appropriate type
%%--------------------------------------------------------------------
@@ -723,6 +746,11 @@ cipher_suites(Suites, false) ->
cipher_suites(Suites, true) ->
Suites.
+srp_user(#ssl_options{srp_identity = {UserName, _}}) ->
+ #srp{username = UserName};
+srp_user(_) ->
+ undefined.
+
renegotiation_info(client, _, false) ->
#renegotiation_info{renegotiated_connection = undefined};
renegotiation_info(server, ConnectionStates, false) ->
@@ -805,6 +833,11 @@ select_next_protocol(Protocols, NextProtocolSelector) ->
Protocol
end.
+handle_srp_info(undefined, Session) ->
+ Session;
+handle_srp_info(#srp{username = Username}, Session) ->
+ Session#session{srp_username = Username}.
+
handle_renegotiation_info(_, #renegotiation_info{renegotiated_connection = ?byte(0)},
ConnectionStates, false, _, _) ->
{ok, ssl_record:set_renegotiation_flag(true, ConnectionStates)};
@@ -987,6 +1020,7 @@ dec_hs(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
DecodedExtensions = dec_hello_extensions(Extensions),
RenegotiationInfo = proplists:get_value(renegotiation_info, DecodedExtensions, undefined),
+ SRP = proplists:get_value(srp, DecodedExtensions, undefined),
HashSigns = proplists:get_value(hash_signs, DecodedExtensions, undefined),
NextProtocolNegotiation = proplists:get_value(next_protocol_negotiation, DecodedExtensions, undefined),
@@ -997,6 +1031,7 @@ dec_hs(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
cipher_suites = from_2bytes(CipherSuites),
compression_methods = Comp_methods,
renegotiation_info = RenegotiationInfo,
+ srp = SRP,
hash_signs = HashSigns,
next_protocol_negotiation = NextProtocolNegotiation
};
@@ -1088,7 +1123,10 @@ dec_client_key(<<?UINT16(Len), Id:Len/binary, PKEPMS/binary>>,
#client_rsa_psk_identity{identity = Id, exchange_keys = #encrypted_premaster_secret{premaster_secret = PKEPMS}};
dec_client_key(<<?UINT16(Len), Id:Len/binary, ?UINT16(_), PKEPMS/binary>>,
?KEY_EXCHANGE_RSA_PSK, _) ->
- #client_rsa_psk_identity{identity = Id, exchange_keys = #encrypted_premaster_secret{premaster_secret = PKEPMS}}.
+ #client_rsa_psk_identity{identity = Id, exchange_keys = #encrypted_premaster_secret{premaster_secret = PKEPMS}};
+dec_client_key(<<?UINT16(ALen), A:ALen/binary>>,
+ ?KEY_EXCHANGE_SRP, _) ->
+ #client_srp_public{srp_a = A}.
dec_ske_params(Len, Keys, Version) ->
<<Params:Len/bytes, Signature/binary>> = Keys,
@@ -1147,6 +1185,17 @@ dec_server_key(<<?UINT16(Len), IdentityHint:Len/binary,
params_bin = BinMsg,
hashsign = HashSign,
signature = Signature};
+dec_server_key(<<?UINT16(NLen), N:NLen/binary,
+ ?UINT16(GLen), G:GLen/binary,
+ ?BYTE(SLen), S:SLen/binary,
+ ?UINT16(BLen), B:BLen/binary, _/binary>> = KeyStruct,
+ ?KEY_EXCHANGE_SRP, Version) ->
+ Params = #server_srp_params{srp_n = N, srp_g = G, srp_s = S, srp_b = B},
+ {BinMsg, HashSign, Signature} = dec_ske_params(NLen + GLen + SLen + BLen + 7, KeyStruct, Version),
+ #server_key_params{params = Params,
+ params_bin = BinMsg,
+ hashsign = HashSign,
+ signature = Signature};
dec_server_key(_, _, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)).
@@ -1174,6 +1223,11 @@ dec_hello_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binar
dec_hello_extensions(Rest, [{renegotiation_info,
#renegotiation_info{renegotiated_connection = RenegotiateInfo}} | Acc]);
+dec_hello_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen), SRP:SRPLen/binary, Rest/binary>>, Acc)
+ when Len == SRPLen + 2 ->
+ dec_hello_extensions(Rest, [{srp,
+ #srp{username = SRP}} | Acc]);
+
dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
SignAlgoListLen = Len - 2,
@@ -1231,6 +1285,7 @@ enc_hs(#client_hello{client_version = {Major, Minor},
cipher_suites = CipherSuites,
compression_methods = CompMethods,
renegotiation_info = RenegotiationInfo,
+ srp = SRP,
hash_signs = HashSigns,
next_protocol_negotiation = NextProtocolNegotiation}, _Version) ->
SIDLength = byte_size(SessionID),
@@ -1238,7 +1293,7 @@ enc_hs(#client_hello{client_version = {Major, Minor},
CmLength = byte_size(BinCompMethods),
BinCipherSuites = list_to_binary(CipherSuites),
CsLength = byte_size(BinCipherSuites),
- Extensions0 = hello_extensions(RenegotiationInfo, NextProtocolNegotiation),
+ Extensions0 = hello_extensions(RenegotiationInfo, SRP, NextProtocolNegotiation),
Extensions1 = if
Major == 3, Minor >=3 -> Extensions0 ++ hello_extensions(HashSigns);
true -> Extensions0
@@ -1333,7 +1388,10 @@ enc_cke(Identity = #client_rsa_psk_identity{identity = undefined}, Version) ->
enc_cke(#client_rsa_psk_identity{identity = Id, exchange_keys = ExchangeKeys}, Version) ->
EncPMS = enc_cke(ExchangeKeys, Version),
Len = byte_size(Id),
- <<?UINT16(Len), Id/binary, EncPMS/binary>>.
+ <<?UINT16(Len), Id/binary, EncPMS/binary>>;
+enc_cke(#client_srp_public{srp_a = A}, _) ->
+ Len = byte_size(A),
+ <<?UINT16(Len), A/binary>>.
enc_server_key(#server_dh_params{dh_p = P, dh_g = G, dh_y = Y}) ->
PLen = byte_size(P),
@@ -1353,7 +1411,14 @@ enc_server_key(#server_dhe_psk_params{
GLen = byte_size(G),
YLen = byte_size(Y),
<<?UINT16(Len), PskIdentityHint/binary,
- ?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>.
+ ?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>;
+enc_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),
+ SLen = byte_size(S),
+ BLen = byte_size(B),
+ <<?UINT16(NLen), N/binary, ?UINT16(GLen), G/binary,
+ ?BYTE(SLen), S/binary, ?UINT16(BLen), B/binary>>.
enc_sign({_, anon}, _Sign, _Version) ->
<<>>;
@@ -1369,13 +1434,20 @@ enc_sign(_HashSign, Sign, _Version) ->
hello_extensions(RenegotiationInfo, NextProtocolNegotiation) ->
hello_extensions(RenegotiationInfo) ++ next_protocol_extension(NextProtocolNegotiation).
+hello_extensions(RenegotiationInfo, SRP, NextProtocolNegotiation) ->
+ hello_extensions(RenegotiationInfo) ++ hello_extensions(SRP) ++ next_protocol_extension(NextProtocolNegotiation).
+
%% Renegotiation info
hello_extensions(#renegotiation_info{renegotiated_connection = undefined}) ->
[];
hello_extensions(#renegotiation_info{} = Info) ->
[Info];
+hello_extensions(#srp{} = Info) ->
+ [Info];
hello_extensions(#hash_sign_algos{} = Info) ->
- [Info].
+ [Info];
+hello_extensions(undefined) ->
+ [].
next_protocol_extension(undefined) ->
[];
@@ -1402,6 +1474,11 @@ enc_hello_extensions([#renegotiation_info{renegotiated_connection = Info} | Rest
Len = InfoLen +1,
enc_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen), Info/binary, Acc/binary>>);
+enc_hello_extensions([#srp{username = UserName} | Rest], Acc) ->
+ SRPLen = byte_size(UserName),
+ Len = SRPLen + 2,
+ enc_hello_extensions(Rest, <<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen), UserName/binary, Acc/binary>>);
+
enc_hello_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Acc) ->
SignAlgoList = << <<(ssl_cipher:hash_algorithm(Hash)):8, (ssl_cipher:sign_algorithm(Sign)):8>> ||
{Hash, Sign} <- HashSignAlgos >>,
@@ -1517,6 +1594,9 @@ key_exchange_alg(dhe_psk) ->
?KEY_EXCHANGE_DHE_PSK;
key_exchange_alg(rsa_psk) ->
?KEY_EXCHANGE_RSA_PSK;
+key_exchange_alg(Alg)
+ when Alg == srp_rsa; Alg == srp_dss; Alg == srp_anon ->
+ ?KEY_EXCHANGE_SRP;
key_exchange_alg(_) ->
?NULL.
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index e35f68409e..1fbb88f5f6 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -48,6 +48,7 @@
compression_method,
cipher_suite,
master_secret,
+ srp_username,
is_resumable,
time_stamp
}).
@@ -99,6 +100,7 @@
cipher_suites, % cipher_suites<2..2^16-1>
compression_methods, % compression_methods<1..2^8-1>,
renegotiation_info,
+ srp, % srp username to send
hash_signs, % supported combinations of hashes/signature algos
next_protocol_negotiation = undefined % [binary()]
}).
@@ -131,6 +133,7 @@
-define(KEY_EXCHANGE_PSK, 2).
-define(KEY_EXCHANGE_DHE_PSK, 3).
-define(KEY_EXCHANGE_RSA_PSK, 4).
+-define(KEY_EXCHANGE_SRP, 5).
-record(server_rsa_params, {
rsa_modulus, %% opaque RSA_modulus<1..2^16-1>
@@ -152,6 +155,13 @@
dh_params
}).
+-record(server_srp_params, {
+ srp_n, %% opaque srp_N<1..2^16-1>
+ srp_g, %% opaque srp_g<1..2^16-1>
+ srp_s, %% opaque srp_s<1..2^8-1>
+ srp_b %% opaque srp_B<1..2^16-1>
+ }).
+
-record(server_key_exchange, {
exchange_keys
}).
@@ -235,6 +245,10 @@
exchange_keys
}).
+-record(client_srp_public, {
+ srp_a
+ }).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Certificate verify - RFC 4346 section 7.4.8
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -261,6 +275,15 @@
}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% SRP RFC 5054 section 2.8.1.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(SRP_EXT, 12).
+
+-record(srp, {
+ username
+ }).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Signature Algorithms RFC 5746 section 7.4.1.4.1.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(SIGNATURE_ALGORITHMS_EXT, 13).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index fc441a3f01..96a1c8e1ce 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -92,6 +92,7 @@
dhfile, % file()
user_lookup_fun, % server option, fun to lookup the user
psk_identity, % binary
+ srp_identity, % client option {User, Password}
ciphers, %
%% Local policy for the server if it want's to reuse the session
%% or not. Defaluts to allways returning true.
diff --git a/lib/ssl/src/ssl_srp.hrl b/lib/ssl/src/ssl_srp.hrl
new file mode 100644
index 0000000000..ab2be33ab2
--- /dev/null
+++ b/lib/ssl/src/ssl_srp.hrl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Record definition for the TLS SRP protocol
+%% see RFC 5054
+%%----------------------------------------------------------------------
+
+-record(srp_user, {
+ generator :: binary(),
+ prime :: binary(),
+ salt :: binary(),
+ verifier :: binary()
+ }).
diff --git a/lib/ssl/src/ssl_srp_primes.erl b/lib/ssl/src/ssl_srp_primes.erl
new file mode 100644
index 0000000000..ca20a8d673
--- /dev/null
+++ b/lib/ssl/src/ssl_srp_primes.erl
@@ -0,0 +1,506 @@
+-module(ssl_srp_primes).
+
+-export([get_srp_params/1, check_srp_params/2]).
+
+-define(PRIME_1024, <<16#EE, 16#AF, 16#0A, 16#B9, 16#AD, 16#B3, 16#8D,
+ 16#D6, 16#9C, 16#33, 16#F8, 16#0A, 16#FA, 16#8F,
+ 16#C5, 16#E8, 16#60, 16#72, 16#61, 16#87, 16#75,
+ 16#FF, 16#3C, 16#0B, 16#9E, 16#A2, 16#31, 16#4C,
+ 16#9C, 16#25, 16#65, 16#76, 16#D6, 16#74, 16#DF,
+ 16#74, 16#96, 16#EA, 16#81, 16#D3, 16#38, 16#3B,
+ 16#48, 16#13, 16#D6, 16#92, 16#C6, 16#E0, 16#E0,
+ 16#D5, 16#D8, 16#E2, 16#50, 16#B9, 16#8B, 16#E4,
+ 16#8E, 16#49, 16#5C, 16#1D, 16#60, 16#89, 16#DA,
+ 16#D1, 16#5D, 16#C7, 16#D7, 16#B4, 16#61, 16#54,
+ 16#D6, 16#B6, 16#CE, 16#8E, 16#F4, 16#AD, 16#69,
+ 16#B1, 16#5D, 16#49, 16#82, 16#55, 16#9B, 16#29,
+ 16#7B, 16#CF, 16#18, 16#85, 16#C5, 16#29, 16#F5,
+ 16#66, 16#66, 16#0E, 16#57, 16#EC, 16#68, 16#ED,
+ 16#BC, 16#3C, 16#05, 16#72, 16#6C, 16#C0, 16#2F,
+ 16#D4, 16#CB, 16#F4, 16#97, 16#6E, 16#AA, 16#9A,
+ 16#FD, 16#51, 16#38, 16#FE, 16#83, 16#76, 16#43,
+ 16#5B, 16#9F, 16#C6, 16#1D, 16#2F, 16#C0, 16#EB,
+ 16#06, 16#E3>>).
+-define(GENERATOR_1024, <<2>>).
+
+
+-define(PRIME_1536, <<16#9D, 16#EF, 16#3C, 16#AF, 16#B9, 16#39, 16#27,
+ 16#7A, 16#B1, 16#F1, 16#2A, 16#86, 16#17, 16#A4,
+ 16#7B, 16#BB, 16#DB, 16#A5, 16#1D, 16#F4, 16#99,
+ 16#AC, 16#4C, 16#80, 16#BE, 16#EE, 16#A9, 16#61,
+ 16#4B, 16#19, 16#CC, 16#4D, 16#5F, 16#4F, 16#5F,
+ 16#55, 16#6E, 16#27, 16#CB, 16#DE, 16#51, 16#C6,
+ 16#A9, 16#4B, 16#E4, 16#60, 16#7A, 16#29, 16#15,
+ 16#58, 16#90, 16#3B, 16#A0, 16#D0, 16#F8, 16#43,
+ 16#80, 16#B6, 16#55, 16#BB, 16#9A, 16#22, 16#E8,
+ 16#DC, 16#DF, 16#02, 16#8A, 16#7C, 16#EC, 16#67,
+ 16#F0, 16#D0, 16#81, 16#34, 16#B1, 16#C8, 16#B9,
+ 16#79, 16#89, 16#14, 16#9B, 16#60, 16#9E, 16#0B,
+ 16#E3, 16#BA, 16#B6, 16#3D, 16#47, 16#54, 16#83,
+ 16#81, 16#DB, 16#C5, 16#B1, 16#FC, 16#76, 16#4E,
+ 16#3F, 16#4B, 16#53, 16#DD, 16#9D, 16#A1, 16#15,
+ 16#8B, 16#FD, 16#3E, 16#2B, 16#9C, 16#8C, 16#F5,
+ 16#6E, 16#DF, 16#01, 16#95, 16#39, 16#34, 16#96,
+ 16#27, 16#DB, 16#2F, 16#D5, 16#3D, 16#24, 16#B7,
+ 16#C4, 16#86, 16#65, 16#77, 16#2E, 16#43, 16#7D,
+ 16#6C, 16#7F, 16#8C, 16#E4, 16#42, 16#73, 16#4A,
+ 16#F7, 16#CC, 16#B7, 16#AE, 16#83, 16#7C, 16#26,
+ 16#4A, 16#E3, 16#A9, 16#BE, 16#B8, 16#7F, 16#8A,
+ 16#2F, 16#E9, 16#B8, 16#B5, 16#29, 16#2E, 16#5A,
+ 16#02, 16#1F, 16#FF, 16#5E, 16#91, 16#47, 16#9E,
+ 16#8C, 16#E7, 16#A2, 16#8C, 16#24, 16#42, 16#C6,
+ 16#F3, 16#15, 16#18, 16#0F, 16#93, 16#49, 16#9A,
+ 16#23, 16#4D, 16#CF, 16#76, 16#E3, 16#FE, 16#D1,
+ 16#35, 16#F9, 16#BB>>).
+-define(GENERATOR_1536, <<2>>).
+
+-define(PRIME_2048, <<16#AC, 16#6B, 16#DB, 16#41, 16#32, 16#4A, 16#9A,
+ 16#9B, 16#F1, 16#66, 16#DE, 16#5E, 16#13, 16#89,
+ 16#58, 16#2F, 16#AF, 16#72, 16#B6, 16#65, 16#19,
+ 16#87, 16#EE, 16#07, 16#FC, 16#31, 16#92, 16#94,
+ 16#3D, 16#B5, 16#60, 16#50, 16#A3, 16#73, 16#29,
+ 16#CB, 16#B4, 16#A0, 16#99, 16#ED, 16#81, 16#93,
+ 16#E0, 16#75, 16#77, 16#67, 16#A1, 16#3D, 16#D5,
+ 16#23, 16#12, 16#AB, 16#4B, 16#03, 16#31, 16#0D,
+ 16#CD, 16#7F, 16#48, 16#A9, 16#DA, 16#04, 16#FD,
+ 16#50, 16#E8, 16#08, 16#39, 16#69, 16#ED, 16#B7,
+ 16#67, 16#B0, 16#CF, 16#60, 16#95, 16#17, 16#9A,
+ 16#16, 16#3A, 16#B3, 16#66, 16#1A, 16#05, 16#FB,
+ 16#D5, 16#FA, 16#AA, 16#E8, 16#29, 16#18, 16#A9,
+ 16#96, 16#2F, 16#0B, 16#93, 16#B8, 16#55, 16#F9,
+ 16#79, 16#93, 16#EC, 16#97, 16#5E, 16#EA, 16#A8,
+ 16#0D, 16#74, 16#0A, 16#DB, 16#F4, 16#FF, 16#74,
+ 16#73, 16#59, 16#D0, 16#41, 16#D5, 16#C3, 16#3E,
+ 16#A7, 16#1D, 16#28, 16#1E, 16#44, 16#6B, 16#14,
+ 16#77, 16#3B, 16#CA, 16#97, 16#B4, 16#3A, 16#23,
+ 16#FB, 16#80, 16#16, 16#76, 16#BD, 16#20, 16#7A,
+ 16#43, 16#6C, 16#64, 16#81, 16#F1, 16#D2, 16#B9,
+ 16#07, 16#87, 16#17, 16#46, 16#1A, 16#5B, 16#9D,
+ 16#32, 16#E6, 16#88, 16#F8, 16#77, 16#48, 16#54,
+ 16#45, 16#23, 16#B5, 16#24, 16#B0, 16#D5, 16#7D,
+ 16#5E, 16#A7, 16#7A, 16#27, 16#75, 16#D2, 16#EC,
+ 16#FA, 16#03, 16#2C, 16#FB, 16#DB, 16#F5, 16#2F,
+ 16#B3, 16#78, 16#61, 16#60, 16#27, 16#90, 16#04,
+ 16#E5, 16#7A, 16#E6, 16#AF, 16#87, 16#4E, 16#73,
+ 16#03, 16#CE, 16#53, 16#29, 16#9C, 16#CC, 16#04,
+ 16#1C, 16#7B, 16#C3, 16#08, 16#D8, 16#2A, 16#56,
+ 16#98, 16#F3, 16#A8, 16#D0, 16#C3, 16#82, 16#71,
+ 16#AE, 16#35, 16#F8, 16#E9, 16#DB, 16#FB, 16#B6,
+ 16#94, 16#B5, 16#C8, 16#03, 16#D8, 16#9F, 16#7A,
+ 16#E4, 16#35, 16#DE, 16#23, 16#6D, 16#52, 16#5F,
+ 16#54, 16#75, 16#9B, 16#65, 16#E3, 16#72, 16#FC,
+ 16#D6, 16#8E, 16#F2, 16#0F, 16#A7, 16#11, 16#1F,
+ 16#9E, 16#4A, 16#FF, 16#73>>).
+-define(GENERATOR_2048, <<2>>).
+
+-define(PRIME_3072, <<16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#C9, 16#0F, 16#DA, 16#A2, 16#21, 16#68,
+ 16#C2, 16#34, 16#C4, 16#C6, 16#62, 16#8B, 16#80,
+ 16#DC, 16#1C, 16#D1, 16#29, 16#02, 16#4E, 16#08,
+ 16#8A, 16#67, 16#CC, 16#74, 16#02, 16#0B, 16#BE,
+ 16#A6, 16#3B, 16#13, 16#9B, 16#22, 16#51, 16#4A,
+ 16#08, 16#79, 16#8E, 16#34, 16#04, 16#DD, 16#EF,
+ 16#95, 16#19, 16#B3, 16#CD, 16#3A, 16#43, 16#1B,
+ 16#30, 16#2B, 16#0A, 16#6D, 16#F2, 16#5F, 16#14,
+ 16#37, 16#4F, 16#E1, 16#35, 16#6D, 16#6D, 16#51,
+ 16#C2, 16#45, 16#E4, 16#85, 16#B5, 16#76, 16#62,
+ 16#5E, 16#7E, 16#C6, 16#F4, 16#4C, 16#42, 16#E9,
+ 16#A6, 16#37, 16#ED, 16#6B, 16#0B, 16#FF, 16#5C,
+ 16#B6, 16#F4, 16#06, 16#B7, 16#ED, 16#EE, 16#38,
+ 16#6B, 16#FB, 16#5A, 16#89, 16#9F, 16#A5, 16#AE,
+ 16#9F, 16#24, 16#11, 16#7C, 16#4B, 16#1F, 16#E6,
+ 16#49, 16#28, 16#66, 16#51, 16#EC, 16#E4, 16#5B,
+ 16#3D, 16#C2, 16#00, 16#7C, 16#B8, 16#A1, 16#63,
+ 16#BF, 16#05, 16#98, 16#DA, 16#48, 16#36, 16#1C,
+ 16#55, 16#D3, 16#9A, 16#69, 16#16, 16#3F, 16#A8,
+ 16#FD, 16#24, 16#CF, 16#5F, 16#83, 16#65, 16#5D,
+ 16#23, 16#DC, 16#A3, 16#AD, 16#96, 16#1C, 16#62,
+ 16#F3, 16#56, 16#20, 16#85, 16#52, 16#BB, 16#9E,
+ 16#D5, 16#29, 16#07, 16#70, 16#96, 16#96, 16#6D,
+ 16#67, 16#0C, 16#35, 16#4E, 16#4A, 16#BC, 16#98,
+ 16#04, 16#F1, 16#74, 16#6C, 16#08, 16#CA, 16#18,
+ 16#21, 16#7C, 16#32, 16#90, 16#5E, 16#46, 16#2E,
+ 16#36, 16#CE, 16#3B, 16#E3, 16#9E, 16#77, 16#2C,
+ 16#18, 16#0E, 16#86, 16#03, 16#9B, 16#27, 16#83,
+ 16#A2, 16#EC, 16#07, 16#A2, 16#8F, 16#B5, 16#C5,
+ 16#5D, 16#F0, 16#6F, 16#4C, 16#52, 16#C9, 16#DE,
+ 16#2B, 16#CB, 16#F6, 16#95, 16#58, 16#17, 16#18,
+ 16#39, 16#95, 16#49, 16#7C, 16#EA, 16#95, 16#6A,
+ 16#E5, 16#15, 16#D2, 16#26, 16#18, 16#98, 16#FA,
+ 16#05, 16#10, 16#15, 16#72, 16#8E, 16#5A, 16#8A,
+ 16#AA, 16#C4, 16#2D, 16#AD, 16#33, 16#17, 16#0D,
+ 16#04, 16#50, 16#7A, 16#33, 16#A8, 16#55, 16#21,
+ 16#AB, 16#DF, 16#1C, 16#BA, 16#64, 16#EC, 16#FB,
+ 16#85, 16#04, 16#58, 16#DB, 16#EF, 16#0A, 16#8A,
+ 16#EA, 16#71, 16#57, 16#5D, 16#06, 16#0C, 16#7D,
+ 16#B3, 16#97, 16#0F, 16#85, 16#A6, 16#E1, 16#E4,
+ 16#C7, 16#AB, 16#F5, 16#AE, 16#8C, 16#DB, 16#09,
+ 16#33, 16#D7, 16#1E, 16#8C, 16#94, 16#E0, 16#4A,
+ 16#25, 16#61, 16#9D, 16#CE, 16#E3, 16#D2, 16#26,
+ 16#1A, 16#D2, 16#EE, 16#6B, 16#F1, 16#2F, 16#FA,
+ 16#06, 16#D9, 16#8A, 16#08, 16#64, 16#D8, 16#76,
+ 16#02, 16#73, 16#3E, 16#C8, 16#6A, 16#64, 16#52,
+ 16#1F, 16#2B, 16#18, 16#17, 16#7B, 16#20, 16#0C,
+ 16#BB, 16#E1, 16#17, 16#57, 16#7A, 16#61, 16#5D,
+ 16#6C, 16#77, 16#09, 16#88, 16#C0, 16#BA, 16#D9,
+ 16#46, 16#E2, 16#08, 16#E2, 16#4F, 16#A0, 16#74,
+ 16#E5, 16#AB, 16#31, 16#43, 16#DB, 16#5B, 16#FC,
+ 16#E0, 16#FD, 16#10, 16#8E, 16#4B, 16#82, 16#D1,
+ 16#20, 16#A9, 16#3A, 16#D2, 16#CA, 16#FF, 16#FF,
+ 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>).
+-define(GENERATOR_3072, <<5>>).
+
+-define(PRIME_4096, <<16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#C9, 16#0F, 16#DA, 16#A2, 16#21, 16#68,
+ 16#C2, 16#34, 16#C4, 16#C6, 16#62, 16#8B, 16#80,
+ 16#DC, 16#1C, 16#D1, 16#29, 16#02, 16#4E, 16#08,
+ 16#8A, 16#67, 16#CC, 16#74, 16#02, 16#0B, 16#BE,
+ 16#A6, 16#3B, 16#13, 16#9B, 16#22, 16#51, 16#4A,
+ 16#08, 16#79, 16#8E, 16#34, 16#04, 16#DD, 16#EF,
+ 16#95, 16#19, 16#B3, 16#CD, 16#3A, 16#43, 16#1B,
+ 16#30, 16#2B, 16#0A, 16#6D, 16#F2, 16#5F, 16#14,
+ 16#37, 16#4F, 16#E1, 16#35, 16#6D, 16#6D, 16#51,
+ 16#C2, 16#45, 16#E4, 16#85, 16#B5, 16#76, 16#62,
+ 16#5E, 16#7E, 16#C6, 16#F4, 16#4C, 16#42, 16#E9,
+ 16#A6, 16#37, 16#ED, 16#6B, 16#0B, 16#FF, 16#5C,
+ 16#B6, 16#F4, 16#06, 16#B7, 16#ED, 16#EE, 16#38,
+ 16#6B, 16#FB, 16#5A, 16#89, 16#9F, 16#A5, 16#AE,
+ 16#9F, 16#24, 16#11, 16#7C, 16#4B, 16#1F, 16#E6,
+ 16#49, 16#28, 16#66, 16#51, 16#EC, 16#E4, 16#5B,
+ 16#3D, 16#C2, 16#00, 16#7C, 16#B8, 16#A1, 16#63,
+ 16#BF, 16#05, 16#98, 16#DA, 16#48, 16#36, 16#1C,
+ 16#55, 16#D3, 16#9A, 16#69, 16#16, 16#3F, 16#A8,
+ 16#FD, 16#24, 16#CF, 16#5F, 16#83, 16#65, 16#5D,
+ 16#23, 16#DC, 16#A3, 16#AD, 16#96, 16#1C, 16#62,
+ 16#F3, 16#56, 16#20, 16#85, 16#52, 16#BB, 16#9E,
+ 16#D5, 16#29, 16#07, 16#70, 16#96, 16#96, 16#6D,
+ 16#67, 16#0C, 16#35, 16#4E, 16#4A, 16#BC, 16#98,
+ 16#04, 16#F1, 16#74, 16#6C, 16#08, 16#CA, 16#18,
+ 16#21, 16#7C, 16#32, 16#90, 16#5E, 16#46, 16#2E,
+ 16#36, 16#CE, 16#3B, 16#E3, 16#9E, 16#77, 16#2C,
+ 16#18, 16#0E, 16#86, 16#03, 16#9B, 16#27, 16#83,
+ 16#A2, 16#EC, 16#07, 16#A2, 16#8F, 16#B5, 16#C5,
+ 16#5D, 16#F0, 16#6F, 16#4C, 16#52, 16#C9, 16#DE,
+ 16#2B, 16#CB, 16#F6, 16#95, 16#58, 16#17, 16#18,
+ 16#39, 16#95, 16#49, 16#7C, 16#EA, 16#95, 16#6A,
+ 16#E5, 16#15, 16#D2, 16#26, 16#18, 16#98, 16#FA,
+ 16#05, 16#10, 16#15, 16#72, 16#8E, 16#5A, 16#8A,
+ 16#AA, 16#C4, 16#2D, 16#AD, 16#33, 16#17, 16#0D,
+ 16#04, 16#50, 16#7A, 16#33, 16#A8, 16#55, 16#21,
+ 16#AB, 16#DF, 16#1C, 16#BA, 16#64, 16#EC, 16#FB,
+ 16#85, 16#04, 16#58, 16#DB, 16#EF, 16#0A, 16#8A,
+ 16#EA, 16#71, 16#57, 16#5D, 16#06, 16#0C, 16#7D,
+ 16#B3, 16#97, 16#0F, 16#85, 16#A6, 16#E1, 16#E4,
+ 16#C7, 16#AB, 16#F5, 16#AE, 16#8C, 16#DB, 16#09,
+ 16#33, 16#D7, 16#1E, 16#8C, 16#94, 16#E0, 16#4A,
+ 16#25, 16#61, 16#9D, 16#CE, 16#E3, 16#D2, 16#26,
+ 16#1A, 16#D2, 16#EE, 16#6B, 16#F1, 16#2F, 16#FA,
+ 16#06, 16#D9, 16#8A, 16#08, 16#64, 16#D8, 16#76,
+ 16#02, 16#73, 16#3E, 16#C8, 16#6A, 16#64, 16#52,
+ 16#1F, 16#2B, 16#18, 16#17, 16#7B, 16#20, 16#0C,
+ 16#BB, 16#E1, 16#17, 16#57, 16#7A, 16#61, 16#5D,
+ 16#6C, 16#77, 16#09, 16#88, 16#C0, 16#BA, 16#D9,
+ 16#46, 16#E2, 16#08, 16#E2, 16#4F, 16#A0, 16#74,
+ 16#E5, 16#AB, 16#31, 16#43, 16#DB, 16#5B, 16#FC,
+ 16#E0, 16#FD, 16#10, 16#8E, 16#4B, 16#82, 16#D1,
+ 16#20, 16#A9, 16#21, 16#08, 16#01, 16#1A, 16#72,
+ 16#3C, 16#12, 16#A7, 16#87, 16#E6, 16#D7, 16#88,
+ 16#71, 16#9A, 16#10, 16#BD, 16#BA, 16#5B, 16#26,
+ 16#99, 16#C3, 16#27, 16#18, 16#6A, 16#F4, 16#E2,
+ 16#3C, 16#1A, 16#94, 16#68, 16#34, 16#B6, 16#15,
+ 16#0B, 16#DA, 16#25, 16#83, 16#E9, 16#CA, 16#2A,
+ 16#D4, 16#4C, 16#E8, 16#DB, 16#BB, 16#C2, 16#DB,
+ 16#04, 16#DE, 16#8E, 16#F9, 16#2E, 16#8E, 16#FC,
+ 16#14, 16#1F, 16#BE, 16#CA, 16#A6, 16#28, 16#7C,
+ 16#59, 16#47, 16#4E, 16#6B, 16#C0, 16#5D, 16#99,
+ 16#B2, 16#96, 16#4F, 16#A0, 16#90, 16#C3, 16#A2,
+ 16#23, 16#3B, 16#A1, 16#86, 16#51, 16#5B, 16#E7,
+ 16#ED, 16#1F, 16#61, 16#29, 16#70, 16#CE, 16#E2,
+ 16#D7, 16#AF, 16#B8, 16#1B, 16#DD, 16#76, 16#21,
+ 16#70, 16#48, 16#1C, 16#D0, 16#06, 16#91, 16#27,
+ 16#D5, 16#B0, 16#5A, 16#A9, 16#93, 16#B4, 16#EA,
+ 16#98, 16#8D, 16#8F, 16#DD, 16#C1, 16#86, 16#FF,
+ 16#B7, 16#DC, 16#90, 16#A6, 16#C0, 16#8F, 16#4D,
+ 16#F4, 16#35, 16#C9, 16#34, 16#06, 16#31, 16#99,
+ 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF>>).
+-define(GENERATOR_4096, <<5>>).
+
+-define(PRIME_6144, <<16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#C9, 16#0F, 16#DA, 16#A2, 16#21, 16#68,
+ 16#C2, 16#34, 16#C4, 16#C6, 16#62, 16#8B, 16#80,
+ 16#DC, 16#1C, 16#D1, 16#29, 16#02, 16#4E, 16#08,
+ 16#8A, 16#67, 16#CC, 16#74, 16#02, 16#0B, 16#BE,
+ 16#A6, 16#3B, 16#13, 16#9B, 16#22, 16#51, 16#4A,
+ 16#08, 16#79, 16#8E, 16#34, 16#04, 16#DD, 16#EF,
+ 16#95, 16#19, 16#B3, 16#CD, 16#3A, 16#43, 16#1B,
+ 16#30, 16#2B, 16#0A, 16#6D, 16#F2, 16#5F, 16#14,
+ 16#37, 16#4F, 16#E1, 16#35, 16#6D, 16#6D, 16#51,
+ 16#C2, 16#45, 16#E4, 16#85, 16#B5, 16#76, 16#62,
+ 16#5E, 16#7E, 16#C6, 16#F4, 16#4C, 16#42, 16#E9,
+ 16#A6, 16#37, 16#ED, 16#6B, 16#0B, 16#FF, 16#5C,
+ 16#B6, 16#F4, 16#06, 16#B7, 16#ED, 16#EE, 16#38,
+ 16#6B, 16#FB, 16#5A, 16#89, 16#9F, 16#A5, 16#AE,
+ 16#9F, 16#24, 16#11, 16#7C, 16#4B, 16#1F, 16#E6,
+ 16#49, 16#28, 16#66, 16#51, 16#EC, 16#E4, 16#5B,
+ 16#3D, 16#C2, 16#00, 16#7C, 16#B8, 16#A1, 16#63,
+ 16#BF, 16#05, 16#98, 16#DA, 16#48, 16#36, 16#1C,
+ 16#55, 16#D3, 16#9A, 16#69, 16#16, 16#3F, 16#A8,
+ 16#FD, 16#24, 16#CF, 16#5F, 16#83, 16#65, 16#5D,
+ 16#23, 16#DC, 16#A3, 16#AD, 16#96, 16#1C, 16#62,
+ 16#F3, 16#56, 16#20, 16#85, 16#52, 16#BB, 16#9E,
+ 16#D5, 16#29, 16#07, 16#70, 16#96, 16#96, 16#6D,
+ 16#67, 16#0C, 16#35, 16#4E, 16#4A, 16#BC, 16#98,
+ 16#04, 16#F1, 16#74, 16#6C, 16#08, 16#CA, 16#18,
+ 16#21, 16#7C, 16#32, 16#90, 16#5E, 16#46, 16#2E,
+ 16#36, 16#CE, 16#3B, 16#E3, 16#9E, 16#77, 16#2C,
+ 16#18, 16#0E, 16#86, 16#03, 16#9B, 16#27, 16#83,
+ 16#A2, 16#EC, 16#07, 16#A2, 16#8F, 16#B5, 16#C5,
+ 16#5D, 16#F0, 16#6F, 16#4C, 16#52, 16#C9, 16#DE,
+ 16#2B, 16#CB, 16#F6, 16#95, 16#58, 16#17, 16#18,
+ 16#39, 16#95, 16#49, 16#7C, 16#EA, 16#95, 16#6A,
+ 16#E5, 16#15, 16#D2, 16#26, 16#18, 16#98, 16#FA,
+ 16#05, 16#10, 16#15, 16#72, 16#8E, 16#5A, 16#8A,
+ 16#AA, 16#C4, 16#2D, 16#AD, 16#33, 16#17, 16#0D,
+ 16#04, 16#50, 16#7A, 16#33, 16#A8, 16#55, 16#21,
+ 16#AB, 16#DF, 16#1C, 16#BA, 16#64, 16#EC, 16#FB,
+ 16#85, 16#04, 16#58, 16#DB, 16#EF, 16#0A, 16#8A,
+ 16#EA, 16#71, 16#57, 16#5D, 16#06, 16#0C, 16#7D,
+ 16#B3, 16#97, 16#0F, 16#85, 16#A6, 16#E1, 16#E4,
+ 16#C7, 16#AB, 16#F5, 16#AE, 16#8C, 16#DB, 16#09,
+ 16#33, 16#D7, 16#1E, 16#8C, 16#94, 16#E0, 16#4A,
+ 16#25, 16#61, 16#9D, 16#CE, 16#E3, 16#D2, 16#26,
+ 16#1A, 16#D2, 16#EE, 16#6B, 16#F1, 16#2F, 16#FA,
+ 16#06, 16#D9, 16#8A, 16#08, 16#64, 16#D8, 16#76,
+ 16#02, 16#73, 16#3E, 16#C8, 16#6A, 16#64, 16#52,
+ 16#1F, 16#2B, 16#18, 16#17, 16#7B, 16#20, 16#0C,
+ 16#BB, 16#E1, 16#17, 16#57, 16#7A, 16#61, 16#5D,
+ 16#6C, 16#77, 16#09, 16#88, 16#C0, 16#BA, 16#D9,
+ 16#46, 16#E2, 16#08, 16#E2, 16#4F, 16#A0, 16#74,
+ 16#E5, 16#AB, 16#31, 16#43, 16#DB, 16#5B, 16#FC,
+ 16#E0, 16#FD, 16#10, 16#8E, 16#4B, 16#82, 16#D1,
+ 16#20, 16#A9, 16#21, 16#08, 16#01, 16#1A, 16#72,
+ 16#3C, 16#12, 16#A7, 16#87, 16#E6, 16#D7, 16#88,
+ 16#71, 16#9A, 16#10, 16#BD, 16#BA, 16#5B, 16#26,
+ 16#99, 16#C3, 16#27, 16#18, 16#6A, 16#F4, 16#E2,
+ 16#3C, 16#1A, 16#94, 16#68, 16#34, 16#B6, 16#15,
+ 16#0B, 16#DA, 16#25, 16#83, 16#E9, 16#CA, 16#2A,
+ 16#D4, 16#4C, 16#E8, 16#DB, 16#BB, 16#C2, 16#DB,
+ 16#04, 16#DE, 16#8E, 16#F9, 16#2E, 16#8E, 16#FC,
+ 16#14, 16#1F, 16#BE, 16#CA, 16#A6, 16#28, 16#7C,
+ 16#59, 16#47, 16#4E, 16#6B, 16#C0, 16#5D, 16#99,
+ 16#B2, 16#96, 16#4F, 16#A0, 16#90, 16#C3, 16#A2,
+ 16#23, 16#3B, 16#A1, 16#86, 16#51, 16#5B, 16#E7,
+ 16#ED, 16#1F, 16#61, 16#29, 16#70, 16#CE, 16#E2,
+ 16#D7, 16#AF, 16#B8, 16#1B, 16#DD, 16#76, 16#21,
+ 16#70, 16#48, 16#1C, 16#D0, 16#06, 16#91, 16#27,
+ 16#D5, 16#B0, 16#5A, 16#A9, 16#93, 16#B4, 16#EA,
+ 16#98, 16#8D, 16#8F, 16#DD, 16#C1, 16#86, 16#FF,
+ 16#B7, 16#DC, 16#90, 16#A6, 16#C0, 16#8F, 16#4D,
+ 16#F4, 16#35, 16#C9, 16#34, 16#02, 16#84, 16#92,
+ 16#36, 16#C3, 16#FA, 16#B4, 16#D2, 16#7C, 16#70,
+ 16#26, 16#C1, 16#D4, 16#DC, 16#B2, 16#60, 16#26,
+ 16#46, 16#DE, 16#C9, 16#75, 16#1E, 16#76, 16#3D,
+ 16#BA, 16#37, 16#BD, 16#F8, 16#FF, 16#94, 16#06,
+ 16#AD, 16#9E, 16#53, 16#0E, 16#E5, 16#DB, 16#38,
+ 16#2F, 16#41, 16#30, 16#01, 16#AE, 16#B0, 16#6A,
+ 16#53, 16#ED, 16#90, 16#27, 16#D8, 16#31, 16#17,
+ 16#97, 16#27, 16#B0, 16#86, 16#5A, 16#89, 16#18,
+ 16#DA, 16#3E, 16#DB, 16#EB, 16#CF, 16#9B, 16#14,
+ 16#ED, 16#44, 16#CE, 16#6C, 16#BA, 16#CE, 16#D4,
+ 16#BB, 16#1B, 16#DB, 16#7F, 16#14, 16#47, 16#E6,
+ 16#CC, 16#25, 16#4B, 16#33, 16#20, 16#51, 16#51,
+ 16#2B, 16#D7, 16#AF, 16#42, 16#6F, 16#B8, 16#F4,
+ 16#01, 16#37, 16#8C, 16#D2, 16#BF, 16#59, 16#83,
+ 16#CA, 16#01, 16#C6, 16#4B, 16#92, 16#EC, 16#F0,
+ 16#32, 16#EA, 16#15, 16#D1, 16#72, 16#1D, 16#03,
+ 16#F4, 16#82, 16#D7, 16#CE, 16#6E, 16#74, 16#FE,
+ 16#F6, 16#D5, 16#5E, 16#70, 16#2F, 16#46, 16#98,
+ 16#0C, 16#82, 16#B5, 16#A8, 16#40, 16#31, 16#90,
+ 16#0B, 16#1C, 16#9E, 16#59, 16#E7, 16#C9, 16#7F,
+ 16#BE, 16#C7, 16#E8, 16#F3, 16#23, 16#A9, 16#7A,
+ 16#7E, 16#36, 16#CC, 16#88, 16#BE, 16#0F, 16#1D,
+ 16#45, 16#B7, 16#FF, 16#58, 16#5A, 16#C5, 16#4B,
+ 16#D4, 16#07, 16#B2, 16#2B, 16#41, 16#54, 16#AA,
+ 16#CC, 16#8F, 16#6D, 16#7E, 16#BF, 16#48, 16#E1,
+ 16#D8, 16#14, 16#CC, 16#5E, 16#D2, 16#0F, 16#80,
+ 16#37, 16#E0, 16#A7, 16#97, 16#15, 16#EE, 16#F2,
+ 16#9B, 16#E3, 16#28, 16#06, 16#A1, 16#D5, 16#8B,
+ 16#B7, 16#C5, 16#DA, 16#76, 16#F5, 16#50, 16#AA,
+ 16#3D, 16#8A, 16#1F, 16#BF, 16#F0, 16#EB, 16#19,
+ 16#CC, 16#B1, 16#A3, 16#13, 16#D5, 16#5C, 16#DA,
+ 16#56, 16#C9, 16#EC, 16#2E, 16#F2, 16#96, 16#32,
+ 16#38, 16#7F, 16#E8, 16#D7, 16#6E, 16#3C, 16#04,
+ 16#68, 16#04, 16#3E, 16#8F, 16#66, 16#3F, 16#48,
+ 16#60, 16#EE, 16#12, 16#BF, 16#2D, 16#5B, 16#0B,
+ 16#74, 16#74, 16#D6, 16#E6, 16#94, 16#F9, 16#1E,
+ 16#6D, 16#CC, 16#40, 16#24, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#FF, 16#FF, 16#FF, 16#FF>>).
+-define(GENERATOR_6144, <<5>>).
+
+-define(PRIME_8192, <<16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#C9, 16#0F, 16#DA, 16#A2, 16#21, 16#68,
+ 16#C2, 16#34, 16#C4, 16#C6, 16#62, 16#8B, 16#80,
+ 16#DC, 16#1C, 16#D1, 16#29, 16#02, 16#4E, 16#08,
+ 16#8A, 16#67, 16#CC, 16#74, 16#02, 16#0B, 16#BE,
+ 16#A6, 16#3B, 16#13, 16#9B, 16#22, 16#51, 16#4A,
+ 16#08, 16#79, 16#8E, 16#34, 16#04, 16#DD, 16#EF,
+ 16#95, 16#19, 16#B3, 16#CD, 16#3A, 16#43, 16#1B,
+ 16#30, 16#2B, 16#0A, 16#6D, 16#F2, 16#5F, 16#14,
+ 16#37, 16#4F, 16#E1, 16#35, 16#6D, 16#6D, 16#51,
+ 16#C2, 16#45, 16#E4, 16#85, 16#B5, 16#76, 16#62,
+ 16#5E, 16#7E, 16#C6, 16#F4, 16#4C, 16#42, 16#E9,
+ 16#A6, 16#37, 16#ED, 16#6B, 16#0B, 16#FF, 16#5C,
+ 16#B6, 16#F4, 16#06, 16#B7, 16#ED, 16#EE, 16#38,
+ 16#6B, 16#FB, 16#5A, 16#89, 16#9F, 16#A5, 16#AE,
+ 16#9F, 16#24, 16#11, 16#7C, 16#4B, 16#1F, 16#E6,
+ 16#49, 16#28, 16#66, 16#51, 16#EC, 16#E4, 16#5B,
+ 16#3D, 16#C2, 16#00, 16#7C, 16#B8, 16#A1, 16#63,
+ 16#BF, 16#05, 16#98, 16#DA, 16#48, 16#36, 16#1C,
+ 16#55, 16#D3, 16#9A, 16#69, 16#16, 16#3F, 16#A8,
+ 16#FD, 16#24, 16#CF, 16#5F, 16#83, 16#65, 16#5D,
+ 16#23, 16#DC, 16#A3, 16#AD, 16#96, 16#1C, 16#62,
+ 16#F3, 16#56, 16#20, 16#85, 16#52, 16#BB, 16#9E,
+ 16#D5, 16#29, 16#07, 16#70, 16#96, 16#96, 16#6D,
+ 16#67, 16#0C, 16#35, 16#4E, 16#4A, 16#BC, 16#98,
+ 16#04, 16#F1, 16#74, 16#6C, 16#08, 16#CA, 16#18,
+ 16#21, 16#7C, 16#32, 16#90, 16#5E, 16#46, 16#2E,
+ 16#36, 16#CE, 16#3B, 16#E3, 16#9E, 16#77, 16#2C,
+ 16#18, 16#0E, 16#86, 16#03, 16#9B, 16#27, 16#83,
+ 16#A2, 16#EC, 16#07, 16#A2, 16#8F, 16#B5, 16#C5,
+ 16#5D, 16#F0, 16#6F, 16#4C, 16#52, 16#C9, 16#DE,
+ 16#2B, 16#CB, 16#F6, 16#95, 16#58, 16#17, 16#18,
+ 16#39, 16#95, 16#49, 16#7C, 16#EA, 16#95, 16#6A,
+ 16#E5, 16#15, 16#D2, 16#26, 16#18, 16#98, 16#FA,
+ 16#05, 16#10, 16#15, 16#72, 16#8E, 16#5A, 16#8A,
+ 16#AA, 16#C4, 16#2D, 16#AD, 16#33, 16#17, 16#0D,
+ 16#04, 16#50, 16#7A, 16#33, 16#A8, 16#55, 16#21,
+ 16#AB, 16#DF, 16#1C, 16#BA, 16#64, 16#EC, 16#FB,
+ 16#85, 16#04, 16#58, 16#DB, 16#EF, 16#0A, 16#8A,
+ 16#EA, 16#71, 16#57, 16#5D, 16#06, 16#0C, 16#7D,
+ 16#B3, 16#97, 16#0F, 16#85, 16#A6, 16#E1, 16#E4,
+ 16#C7, 16#AB, 16#F5, 16#AE, 16#8C, 16#DB, 16#09,
+ 16#33, 16#D7, 16#1E, 16#8C, 16#94, 16#E0, 16#4A,
+ 16#25, 16#61, 16#9D, 16#CE, 16#E3, 16#D2, 16#26,
+ 16#1A, 16#D2, 16#EE, 16#6B, 16#F1, 16#2F, 16#FA,
+ 16#06, 16#D9, 16#8A, 16#08, 16#64, 16#D8, 16#76,
+ 16#02, 16#73, 16#3E, 16#C8, 16#6A, 16#64, 16#52,
+ 16#1F, 16#2B, 16#18, 16#17, 16#7B, 16#20, 16#0C,
+ 16#BB, 16#E1, 16#17, 16#57, 16#7A, 16#61, 16#5D,
+ 16#6C, 16#77, 16#09, 16#88, 16#C0, 16#BA, 16#D9,
+ 16#46, 16#E2, 16#08, 16#E2, 16#4F, 16#A0, 16#74,
+ 16#E5, 16#AB, 16#31, 16#43, 16#DB, 16#5B, 16#FC,
+ 16#E0, 16#FD, 16#10, 16#8E, 16#4B, 16#82, 16#D1,
+ 16#20, 16#A9, 16#21, 16#08, 16#01, 16#1A, 16#72,
+ 16#3C, 16#12, 16#A7, 16#87, 16#E6, 16#D7, 16#88,
+ 16#71, 16#9A, 16#10, 16#BD, 16#BA, 16#5B, 16#26,
+ 16#99, 16#C3, 16#27, 16#18, 16#6A, 16#F4, 16#E2,
+ 16#3C, 16#1A, 16#94, 16#68, 16#34, 16#B6, 16#15,
+ 16#0B, 16#DA, 16#25, 16#83, 16#E9, 16#CA, 16#2A,
+ 16#D4, 16#4C, 16#E8, 16#DB, 16#BB, 16#C2, 16#DB,
+ 16#04, 16#DE, 16#8E, 16#F9, 16#2E, 16#8E, 16#FC,
+ 16#14, 16#1F, 16#BE, 16#CA, 16#A6, 16#28, 16#7C,
+ 16#59, 16#47, 16#4E, 16#6B, 16#C0, 16#5D, 16#99,
+ 16#B2, 16#96, 16#4F, 16#A0, 16#90, 16#C3, 16#A2,
+ 16#23, 16#3B, 16#A1, 16#86, 16#51, 16#5B, 16#E7,
+ 16#ED, 16#1F, 16#61, 16#29, 16#70, 16#CE, 16#E2,
+ 16#D7, 16#AF, 16#B8, 16#1B, 16#DD, 16#76, 16#21,
+ 16#70, 16#48, 16#1C, 16#D0, 16#06, 16#91, 16#27,
+ 16#D5, 16#B0, 16#5A, 16#A9, 16#93, 16#B4, 16#EA,
+ 16#98, 16#8D, 16#8F, 16#DD, 16#C1, 16#86, 16#FF,
+ 16#B7, 16#DC, 16#90, 16#A6, 16#C0, 16#8F, 16#4D,
+ 16#F4, 16#35, 16#C9, 16#34, 16#02, 16#84, 16#92,
+ 16#36, 16#C3, 16#FA, 16#B4, 16#D2, 16#7C, 16#70,
+ 16#26, 16#C1, 16#D4, 16#DC, 16#B2, 16#60, 16#26,
+ 16#46, 16#DE, 16#C9, 16#75, 16#1E, 16#76, 16#3D,
+ 16#BA, 16#37, 16#BD, 16#F8, 16#FF, 16#94, 16#06,
+ 16#AD, 16#9E, 16#53, 16#0E, 16#E5, 16#DB, 16#38,
+ 16#2F, 16#41, 16#30, 16#01, 16#AE, 16#B0, 16#6A,
+ 16#53, 16#ED, 16#90, 16#27, 16#D8, 16#31, 16#17,
+ 16#97, 16#27, 16#B0, 16#86, 16#5A, 16#89, 16#18,
+ 16#DA, 16#3E, 16#DB, 16#EB, 16#CF, 16#9B, 16#14,
+ 16#ED, 16#44, 16#CE, 16#6C, 16#BA, 16#CE, 16#D4,
+ 16#BB, 16#1B, 16#DB, 16#7F, 16#14, 16#47, 16#E6,
+ 16#CC, 16#25, 16#4B, 16#33, 16#20, 16#51, 16#51,
+ 16#2B, 16#D7, 16#AF, 16#42, 16#6F, 16#B8, 16#F4,
+ 16#01, 16#37, 16#8C, 16#D2, 16#BF, 16#59, 16#83,
+ 16#CA, 16#01, 16#C6, 16#4B, 16#92, 16#EC, 16#F0,
+ 16#32, 16#EA, 16#15, 16#D1, 16#72, 16#1D, 16#03,
+ 16#F4, 16#82, 16#D7, 16#CE, 16#6E, 16#74, 16#FE,
+ 16#F6, 16#D5, 16#5E, 16#70, 16#2F, 16#46, 16#98,
+ 16#0C, 16#82, 16#B5, 16#A8, 16#40, 16#31, 16#90,
+ 16#0B, 16#1C, 16#9E, 16#59, 16#E7, 16#C9, 16#7F,
+ 16#BE, 16#C7, 16#E8, 16#F3, 16#23, 16#A9, 16#7A,
+ 16#7E, 16#36, 16#CC, 16#88, 16#BE, 16#0F, 16#1D,
+ 16#45, 16#B7, 16#FF, 16#58, 16#5A, 16#C5, 16#4B,
+ 16#D4, 16#07, 16#B2, 16#2B, 16#41, 16#54, 16#AA,
+ 16#CC, 16#8F, 16#6D, 16#7E, 16#BF, 16#48, 16#E1,
+ 16#D8, 16#14, 16#CC, 16#5E, 16#D2, 16#0F, 16#80,
+ 16#37, 16#E0, 16#A7, 16#97, 16#15, 16#EE, 16#F2,
+ 16#9B, 16#E3, 16#28, 16#06, 16#A1, 16#D5, 16#8B,
+ 16#B7, 16#C5, 16#DA, 16#76, 16#F5, 16#50, 16#AA,
+ 16#3D, 16#8A, 16#1F, 16#BF, 16#F0, 16#EB, 16#19,
+ 16#CC, 16#B1, 16#A3, 16#13, 16#D5, 16#5C, 16#DA,
+ 16#56, 16#C9, 16#EC, 16#2E, 16#F2, 16#96, 16#32,
+ 16#38, 16#7F, 16#E8, 16#D7, 16#6E, 16#3C, 16#04,
+ 16#68, 16#04, 16#3E, 16#8F, 16#66, 16#3F, 16#48,
+ 16#60, 16#EE, 16#12, 16#BF, 16#2D, 16#5B, 16#0B,
+ 16#74, 16#74, 16#D6, 16#E6, 16#94, 16#F9, 16#1E,
+ 16#6D, 16#BE, 16#11, 16#59, 16#74, 16#A3, 16#92,
+ 16#6F, 16#12, 16#FE, 16#E5, 16#E4, 16#38, 16#77,
+ 16#7C, 16#B6, 16#A9, 16#32, 16#DF, 16#8C, 16#D8,
+ 16#BE, 16#C4, 16#D0, 16#73, 16#B9, 16#31, 16#BA,
+ 16#3B, 16#C8, 16#32, 16#B6, 16#8D, 16#9D, 16#D3,
+ 16#00, 16#74, 16#1F, 16#A7, 16#BF, 16#8A, 16#FC,
+ 16#47, 16#ED, 16#25, 16#76, 16#F6, 16#93, 16#6B,
+ 16#A4, 16#24, 16#66, 16#3A, 16#AB, 16#63, 16#9C,
+ 16#5A, 16#E4, 16#F5, 16#68, 16#34, 16#23, 16#B4,
+ 16#74, 16#2B, 16#F1, 16#C9, 16#78, 16#23, 16#8F,
+ 16#16, 16#CB, 16#E3, 16#9D, 16#65, 16#2D, 16#E3,
+ 16#FD, 16#B8, 16#BE, 16#FC, 16#84, 16#8A, 16#D9,
+ 16#22, 16#22, 16#2E, 16#04, 16#A4, 16#03, 16#7C,
+ 16#07, 16#13, 16#EB, 16#57, 16#A8, 16#1A, 16#23,
+ 16#F0, 16#C7, 16#34, 16#73, 16#FC, 16#64, 16#6C,
+ 16#EA, 16#30, 16#6B, 16#4B, 16#CB, 16#C8, 16#86,
+ 16#2F, 16#83, 16#85, 16#DD, 16#FA, 16#9D, 16#4B,
+ 16#7F, 16#A2, 16#C0, 16#87, 16#E8, 16#79, 16#68,
+ 16#33, 16#03, 16#ED, 16#5B, 16#DD, 16#3A, 16#06,
+ 16#2B, 16#3C, 16#F5, 16#B3, 16#A2, 16#78, 16#A6,
+ 16#6D, 16#2A, 16#13, 16#F8, 16#3F, 16#44, 16#F8,
+ 16#2D, 16#DF, 16#31, 16#0E, 16#E0, 16#74, 16#AB,
+ 16#6A, 16#36, 16#45, 16#97, 16#E8, 16#99, 16#A0,
+ 16#25, 16#5D, 16#C1, 16#64, 16#F3, 16#1C, 16#C5,
+ 16#08, 16#46, 16#85, 16#1D, 16#F9, 16#AB, 16#48,
+ 16#19, 16#5D, 16#ED, 16#7E, 16#A1, 16#B1, 16#D5,
+ 16#10, 16#BD, 16#7E, 16#E7, 16#4D, 16#73, 16#FA,
+ 16#F3, 16#6B, 16#C3, 16#1E, 16#CF, 16#A2, 16#68,
+ 16#35, 16#90, 16#46, 16#F4, 16#EB, 16#87, 16#9F,
+ 16#92, 16#40, 16#09, 16#43, 16#8B, 16#48, 16#1C,
+ 16#6C, 16#D7, 16#88, 16#9A, 16#00, 16#2E, 16#D5,
+ 16#EE, 16#38, 16#2B, 16#C9, 16#19, 16#0D, 16#A6,
+ 16#FC, 16#02, 16#6E, 16#47, 16#95, 16#58, 16#E4,
+ 16#47, 16#56, 16#77, 16#E9, 16#AA, 16#9E, 16#30,
+ 16#50, 16#E2, 16#76, 16#56, 16#94, 16#DF, 16#C8,
+ 16#1F, 16#56, 16#E8, 16#80, 16#B9, 16#6E, 16#71,
+ 16#60, 16#C9, 16#80, 16#DD, 16#98, 16#ED, 16#D3,
+ 16#DF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF, 16#FF,
+ 16#FF, 16#FF>>).
+-define(GENERATOR_8192, <<19>>).
+
+get_srp_params(srp_1024) -> {?GENERATOR_1024, ?PRIME_1024};
+get_srp_params(srp_1536) -> {?GENERATOR_1536, ?PRIME_1536};
+get_srp_params(srp_2048) -> {?GENERATOR_2048, ?PRIME_2048};
+get_srp_params(srp_3072) -> {?GENERATOR_3072, ?PRIME_3072};
+get_srp_params(srp_4096) -> {?GENERATOR_4096, ?PRIME_4096};
+get_srp_params(srp_6144) -> {?GENERATOR_6144, ?PRIME_6144};
+get_srp_params(srp_8192) -> {?GENERATOR_8192, ?PRIME_8192}.
+
+check_srp_params(?GENERATOR_1024, ?PRIME_1024) -> ok;
+check_srp_params(?GENERATOR_1536, ?PRIME_1536) -> ok;
+check_srp_params(?GENERATOR_2048, ?PRIME_2048) -> ok;
+check_srp_params(?GENERATOR_3072, ?PRIME_3072) -> ok;
+check_srp_params(?GENERATOR_4096, ?PRIME_4096) -> ok;
+check_srp_params(?GENERATOR_6144, ?PRIME_6144) -> ok;
+check_srp_params(?GENERATOR_8192, ?PRIME_8192) -> ok;
+check_srp_params(_Generator, _Prime) ->
+ not_accepted.
diff --git a/lib/ssl/src/ssl_srp_primes.hrl b/lib/ssl/src/ssl_srp_primes.hrl
new file mode 100644
index 0000000000..4bd534efbf
--- /dev/null
+++ b/lib/ssl/src/ssl_srp_primes.hrl
@@ -0,0 +1 @@
+-type srp_parameters() :: srp_1024 | srp_1536 | srp_2048 | srp_3072 | srp_4096 | srp_6144 | srp_8192.