aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src')
-rw-r--r--lib/ssl/src/ssl.appup.src2
-rw-r--r--lib/ssl/src/ssl.erl18
-rw-r--r--lib/ssl/src/ssl_app.erl4
-rw-r--r--lib/ssl/src/ssl_certificate.erl10
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl27
-rw-r--r--lib/ssl/src/ssl_cipher.erl12
-rw-r--r--lib/ssl/src/ssl_cipher.hrl2
-rw-r--r--lib/ssl/src/ssl_connection.erl116
-rw-r--r--lib/ssl/src/ssl_handshake.erl54
-rw-r--r--lib/ssl/src/ssl_internal.hrl4
-rw-r--r--lib/ssl/src/ssl_manager.erl46
-rw-r--r--lib/ssl/src/ssl_record.erl11
-rw-r--r--lib/ssl/src/ssl_session.erl2
-rw-r--r--lib/ssl/src/ssl_ssl3.erl7
-rw-r--r--lib/ssl/src/ssl_sup.erl7
15 files changed, 183 insertions, 139 deletions
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 65f23e2f74..88cd73be74 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,6 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
[
+ {"4.0", [{restart_application, ssl}]},
{"3.11.1", [{restart_application, ssl}]},
{"3.11", [{restart_application, ssl}]},
{"3.10", [{restart_application, ssl}]},
@@ -15,6 +16,7 @@
{"3.10.9", [{restart_application, ssl}]}
],
[
+ {"4.0", [{restart_application, ssl}]},
{"3.11.1", [{restart_application, ssl}]},
{"3.11", [{restart_application, ssl}]},
{"3.10", [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index df4cd7c84d..6e26f05c3d 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -77,8 +77,9 @@ stop() ->
application:stop(ssl).
%%--------------------------------------------------------------------
--spec connect(host() | port(), port_num(), list()) -> {ok, #sslsocket{}}.
--spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), list()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), list() | port_num(), timeout() | list()) -> {ok, #sslsocket{}}.
+-spec connect(host() | port(), port_num(), list(), timeout()) -> {ok, #sslsocket{}}.
%%
%% Description: Connect to a ssl server.
%%--------------------------------------------------------------------
@@ -215,8 +216,8 @@ ssl_accept(Socket, SslOptions, Timeout) when is_port(Socket) ->
{ok, #config{cb=CbInfo,ssl=SslOpts, emulated=EmOpts}} ->
{ok, Port} = inet:port(Socket),
ssl_connection:ssl_accept(Port, Socket,
- {SslOpts, EmOpts},
- self(), CbInfo, Timeout)
+ {SslOpts, EmOpts},
+ self(), CbInfo, Timeout)
catch
Error = {error, _Reason} -> Error
end.
@@ -326,7 +327,7 @@ decode_peercert(BinCert, Opts) ->
{ok, BinCert}
end.
-select_part(otp, {ok, Cert}, Opts) ->
+select_part(otp, Cert, Opts) ->
case lists:member(subject, Opts) of
true ->
TBS = Cert#'OTPCertificate'.tbsCertificate,
@@ -335,7 +336,7 @@ select_part(otp, {ok, Cert}, Opts) ->
{ok, Cert}
end;
-select_part(plain, {ok, Cert}, Opts) ->
+select_part(plain, Cert, Opts) ->
case lists:member(subject, Opts) of
true ->
TBS = Cert#'Certificate'.tbsCertificate,
@@ -446,8 +447,8 @@ session_info(#sslsocket{pid = Pid, fd = new_ssl}) ->
ssl_connection:session_info(Pid).
%%---------------------------------------------------------------
--spec versions() -> [{{ssl_app, string()}, {supported, [tls_version()]},
- {available, [tls_version()]}}].
+-spec versions() -> [{ssl_app, string()} | {supported, [tls_atom_version()]} |
+ {available, [tls_atom_version()]}].
%%
%% Description: Returns a list of relevant versions.
%%--------------------------------------------------------------------
@@ -457,6 +458,7 @@ versions() ->
AvailableVsns = ?DEFAULT_SUPPORTED_VERSIONS,
[{ssl_app, ?VSN}, {supported, SupportedVsns}, {available, AvailableVsns}].
+
%%---------------------------------------------------------------
-spec renegotiate(#sslsocket{}) -> ok | {error, reason()}.
%%
diff --git a/lib/ssl/src/ssl_app.erl b/lib/ssl/src/ssl_app.erl
index d9a354086d..8d50fd7bdb 100644
--- a/lib/ssl/src/ssl_app.erl
+++ b/lib/ssl/src/ssl_app.erl
@@ -29,14 +29,14 @@
%%--------------------------------------------------------------------
-spec start(normal | {takeover, node()} | {failover, node()}, list()) ->
- {ok, pid()} | {ok, pid(), term()} | {error, term()}.
+ ignore | {ok, pid()} | {error, term()}.
%%--------------------------------------------------------------------
start(_Type, _StartArgs) ->
ssl_sup:start_link().
%--------------------------------------------------------------------
-spec stop(term())-> ok.
-%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
stop(_State) ->
ok.
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 8a79f75725..917e75157b 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -56,7 +56,7 @@
%%--------------------------------------------------------------------
trusted_cert_and_path(CertChain, CertDbRef, Verify) ->
[Cert | RestPath] = lists:reverse(CertChain),
- {ok, OtpCert} = public_key:pkix_decode_cert(Cert, otp),
+ OtpCert = public_key:pkix_decode_cert(Cert, otp),
IssuerAnPath =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -94,14 +94,14 @@ trusted_cert_and_path(CertChain, CertDbRef, Verify) ->
%%--------------------------------------------------------------------
-spec certificate_chain(undefined | binary(), certdb_ref()) ->
- {error, no_cert} | [der_cert()].
+ {error, no_cert} | {ok, [der_cert()]}.
%%
%% Description: Return the certificate chain to send to peer.
%%--------------------------------------------------------------------
certificate_chain(undefined, _CertsDbRef) ->
{error, no_cert};
certificate_chain(OwnCert, CertsDbRef) ->
- {ok, ErlCert} = public_key:pkix_decode_cert(OwnCert, otp),
+ ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
certificate_chain(ErlCert, OwnCert, CertsDbRef, [OwnCert]).
%%--------------------------------------------------------------------
-spec file_to_certificats(string()) -> [der_cert()].
@@ -110,7 +110,7 @@ certificate_chain(OwnCert, CertsDbRef) ->
%%--------------------------------------------------------------------
file_to_certificats(File) ->
{ok, List} = ssl_manager:cache_pem_file(File),
- [Bin || {cert, Bin, not_encrypted} <- List].
+ [Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
-spec validate_extensions([#'Extension'{}], term(), [#'Extension'{}],
boolean(), list(), client | server) -> {[#'Extension'{}], term(), list()}.
@@ -219,7 +219,7 @@ certificate_chain(CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
case ssl_manager:lookup_trusted_cert(CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
- {ok, ErlCert} = public_key:pkix_decode_cert(IssuerCert, otp),
+ ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
CertsDbRef, [IssuerCert | Chain]);
_ ->
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index e953821057..00d3079cb3 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -54,10 +54,9 @@ remove(Dbs) ->
lists:foreach(fun(Db) -> true = ets:delete(Db) end, Dbs).
%%--------------------------------------------------------------------
--spec lookup_trusted_cert(reference(), serialnumber(), issuer()) -> {der_cert(), #'OTPCertificate'{}}.
+-spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
+ undefined | {ok, {der_cert(), #'OTPCertificate'{}}}.
-%% SerialNumber = integer()
-%% Issuer = {rdnSequence, IssuerAttrs}
%%
%% Description: Retrives the trusted certificate identified by
%% <SerialNumber, Issuer>. Ref is used as it is specified
@@ -101,10 +100,11 @@ add_trusted_certs(Pid, File, [CertsDb, FileToRefDb, PidToFileDb]) ->
%% Description: Cache file as binary in DB
%%--------------------------------------------------------------------
cache_pem_file(Pid, File, [CertsDb, _FileToRefDb, PidToFileDb]) ->
- Res = {ok, Content} = public_key:pem_to_der(File),
+ {ok, PemBin} = file:read_file(File),
+ Content = public_key:pem_decode(PemBin),
insert({file, File}, Content, CertsDb),
insert(Pid, File, PidToFileDb),
- Res.
+ {ok, Content}.
%%--------------------------------------------------------------------
-spec remove_trusted_certs(pid(), certdb_ref()) -> term().
@@ -138,13 +138,13 @@ remove_trusted_certs(Pid, [CertsDb, FileToRefDb, PidToFileDb]) ->
end.
%%--------------------------------------------------------------------
--spec issuer_candidate(no_candidate | cert_key()) ->
- {cert_key(), der_cert()} | no_more_candidates.
+-spec issuer_candidate(no_candidate | cert_key() | {file, term()}) ->
+ {cert_key(),{der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: If a certificat does not define its issuer through
%% the extension 'ce-authorityKeyIdentifier' we can
%% try to find the issuer in the database over known
-%% certificates.
+%% certificates.
%%--------------------------------------------------------------------
issuer_candidate(no_candidate) ->
Db = certificate_db_name(),
@@ -203,14 +203,15 @@ remove_certs(Ref, CertsDb) ->
ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}).
add_certs_from_file(File, Ref, CertsDb) ->
- Decode = fun(Cert) ->
- {ok, ErlCert} = public_key:pkix_decode_cert(Cert, otp),
+ Add = fun(Cert) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- Issuer = public_key:pkix_normalize_general_name(
+ Issuer = public_key:pkix_normalize_name(
TBSCertificate#'OTPTBSCertificate'.issuer),
insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb)
end,
- {ok,Der} = public_key:pem_to_der(File),
- [Decode(Cert) || {cert, Cert, not_encrypted} <- Der].
+ {ok, PemBin} = file:read_file(File),
+ PemEntries = public_key:pem_decode(PemBin),
+ [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries].
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index a6e80047c2..8230149304 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -40,7 +40,7 @@
-compile(inline).
%%--------------------------------------------------------------------
--spec security_parameters(erl_cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
@@ -119,7 +119,7 @@ block_cipher(Fun, BlockSz, #cipher_state{key=Key, iv=IV} = CS0,
%%--------------------------------------------------------------------
-spec decipher(cipher_enum(), integer(), #cipher_state{}, binary(), tls_version()) ->
- {binary(), #cipher_state{}}.
+ {binary(), binary(), #cipher_state{}} | #alert{}.
%%
%% Description: Decrypts the data and the MAC using cipher described
%% by cipher_enum() and updating the cipher state.
@@ -370,7 +370,7 @@ openssl_suite_name(Cipher) ->
filter(undefined, Ciphers) ->
Ciphers;
filter(DerCert, Ciphers) ->
- {ok, OtpCert} = public_key:pkix_decode_cert(DerCert, otp),
+ OtpCert = public_key:pkix_decode_cert(DerCert, otp),
SigAlg = OtpCert#'OTPCertificate'.signatureAlgorithm,
case ssl_certificate:signature_type(SigAlg#'SignatureAlgorithm'.algorithm) of
rsa ->
@@ -506,6 +506,12 @@ generic_stream_cipher_from_bin(T, HashSz) ->
is_correct_padding(_, {3, 0}) ->
true;
+%% For interoperability reasons we do not check the padding in TLS 1.0 as it
+%% is not strictly required and breaks interopability with for instance
+%% Google.
+is_correct_padding(_, {3, 1}) ->
+ true;
+%% Padding must be check in TLS 1.1 and after
is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) ->
list_to_binary(lists:duplicate(Len, Len)) == Padding.
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index 19de709d9c..8bd68cc190 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -28,7 +28,7 @@
-type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc'
| aes_128_cbc | aes_256_cbc.
--type hash() :: sha | md5.
+-type hash() :: null | sha | md5.
-type erl_cipher_suite() :: {key_algo(), cipher(), hash()}.
-type cipher_suite() :: binary().
-type cipher_enum() :: integer().
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 5b4b129e30..76422155a5 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -125,8 +125,9 @@ send(Pid, Data) ->
recv(Pid, Length, Timeout) ->
sync_send_all_state_event(Pid, {recv, Length}, Timeout).
%%--------------------------------------------------------------------
--spec connect(host(), port_num(), port(), list(), pid(), tuple(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
+-spec connect(host(), port_num(), port(), {#ssl_options{}, #socket_options{}},
+ pid(), tuple(), timeout()) ->
+ {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Connect to a ssl server.
%%--------------------------------------------------------------------
@@ -138,7 +139,8 @@ connect(Host, Port, Socket, Options, User, CbInfo, Timeout) ->
{error, ssl_not_started}
end.
%%--------------------------------------------------------------------
--spec ssl_accept(port_num(), port(), list(), pid(), tuple(), timeout()) ->
+-spec ssl_accept(port_num(), port(), {#ssl_options{}, #socket_options{}},
+ pid(), tuple(), timeout()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on a ssl listen socket. e.i. performs
@@ -253,7 +255,7 @@ session_info(ConnectionPid) ->
sync_send_all_state_event(ConnectionPid, session_info).
%%--------------------------------------------------------------------
--spec peer_certificate(pid()) -> {ok, binary()} | {error, reason()}.
+-spec peer_certificate(pid()) -> {ok, binary()| undefined} | {error, reason()}.
%%
%% Description: Returns the peer cert
%%--------------------------------------------------------------------
@@ -288,9 +290,10 @@ start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
%% gen_fsm callbacks
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, state_name(), #state{}}
- | {ok, state_name(), #state{}, timeout()} |
- ignore | {stop, term()}.
+-spec init(list()) -> {ok, state_name(), #state{}} | {stop, term()}.
+%% Possible return values not used now.
+%% | {ok, state_name(), #state{}, timeout()} |
+%% ignore
%% Description:Whenever a gen_fsm is started using gen_fsm:start/[3,4] or
%% gen_fsm:start_link/3,4, this function is called by the new process to
%% initialize.
@@ -720,7 +723,9 @@ connection(#client_hello{} = Hello, #state{role = server} = State) ->
connection(Msg, State) ->
handle_unexpected_message(Msg, connection, State).
%%--------------------------------------------------------------------
--spec handle_event(term(), state_name(), #state{}) -> gen_fsm_state_return().
+-spec handle_event(term(), state_name(), #state{}) -> term().
+%% As it is not currently used gen_fsm_state_return() makes
+%% dialyzer unhappy!
%%
%% Description: Whenever a gen_fsm receives an event sent using
%% gen_fsm:send_all_state_event/2, this function is called to handle
@@ -1038,20 +1043,22 @@ ssl_init(SslOpts, Role) ->
init_certificates(#ssl_options{cacertfile = CACertFile,
certfile = CertFile}, Role) ->
+ {ok, CertDbRef, CacheRef} =
+ try
+ {ok, _, _} = ssl_manager:connection_init(CACertFile, Role)
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile,
+ erlang:get_stacktrace())
+ end,
+ init_certificates(CertDbRef, CacheRef, CertFile, Role).
- case ssl_manager:connection_init(CACertFile, Role) of
- {ok, CertDbRef, CacheRef} ->
- init_certificates(CertDbRef, CacheRef, CertFile, Role);
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, CACertFile, ecacertfile,
- erlang:get_stacktrace())
- end.
init_certificates(CertDbRef, CacheRef, CertFile, client) ->
try
[OwnCert] = ssl_certificate:file_to_certificats(CertFile),
{ok, CertDbRef, CacheRef, OwnCert}
- catch _E:_R ->
+ catch _Error:_Reason ->
{ok, CertDbRef, CacheRef, undefined}
end;
@@ -1068,15 +1075,15 @@ init_certificates(CertDbRef, CacheRef, CertFile, server) ->
init_private_key(undefined, "", _Password, client) ->
undefined;
init_private_key(undefined, KeyFile, Password, _) ->
- case ssl_manager:cache_pem_file(KeyFile) of
- {ok, List} ->
- [Der] = [Der || Der = {PKey, _ , _} <- List,
- PKey =:= rsa_private_key orelse
- PKey =:= dsa_private_key],
- {ok, Decoded} = public_key:decode_private_key(Der,Password),
- Decoded;
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, KeyFile, ekeyfile,
+ try
+ {ok, List} = ssl_manager:cache_pem_file(KeyFile),
+ [PemEntry] = [PemEntry || PemEntry = {PKey, _ , _} <- List,
+ PKey =:= 'RSAPrivateKey' orelse
+ PKey =:= 'DSAPrivateKey'],
+ public_key:pem_entry_decode(PemEntry, Password)
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile,
erlang:get_stacktrace())
end;
@@ -1088,6 +1095,7 @@ handle_file_error(Line, Error, {badmatch, Reason}, File, Throw, Stack) ->
handle_file_error(Line, Error, Reason, File, Throw, Stack) ->
file_error(Line, Error, Reason, File, Throw, Stack).
+-spec(file_error/6 :: (_,_,_,_,_,_) -> no_return()).
file_error(Line, Error, Reason, File, Throw, Stack) ->
Report = io_lib:format("SSL: ~p: ~p:~p ~s~n ~p~n",
[Line, Error, Reason, File, Stack]),
@@ -1099,17 +1107,18 @@ init_diffie_hellman(_, client) ->
init_diffie_hellman(undefined, _) ->
?DEFAULT_DIFFIE_HELLMAN_PARAMS;
init_diffie_hellman(DHParamFile, server) ->
- case ssl_manager:cache_pem_file(DHParamFile) of
- {ok, List} ->
- case [Der || Der = {dh_params, _ , _} <- List] of
- [Der] ->
- {ok, Decoded} = public_key:decode_dhparams(Der),
- Decoded;
- [] ->
- ?DEFAULT_DIFFIE_HELLMAN_PARAMS
- end;
- {error, Reason} ->
- handle_file_error(?LINE, error, Reason, DHParamFile, edhfile, erlang:get_stacktrace())
+ try
+ {ok, List} = ssl_manager:cache_pem_file(DHParamFile),
+ case [Entry || Entry = {'DHParameter', _ , _} <- List] of
+ [Entry] ->
+ public_key:pem_entry_decode(Entry);
+ [] ->
+ ?DEFAULT_DIFFIE_HELLMAN_PARAMS
+ end
+ catch
+ Error:Reason ->
+ handle_file_error(?LINE, Error, Reason,
+ DHParamFile, edhfile, erlang:get_stacktrace())
end.
sync_send_all_state_event(FsmPid, Event) ->
@@ -1178,7 +1187,7 @@ verify_client_cert(#state{client_certificate_requested = true, role = client,
tls_handshake_hashes = Hashes1};
ignore ->
State;
- #alert{} = Alert ->
+ #alert{} = Alert ->
handle_own_alert(Alert, Version, certify, State)
end;
@@ -1186,18 +1195,19 @@ verify_client_cert(#state{client_certificate_requested = false} = State) ->
State.
do_server_hello(Type, #state{negotiated_version = Version,
- session = Session,
+ session = #session{session_id = SessId} = Session,
connection_states = ConnectionStates0,
renegotiation = {Renegotiation, _}}
= State0) when is_atom(Type) ->
+
ServerHello =
- ssl_handshake:server_hello(Session#session.session_id, Version,
+ ssl_handshake:server_hello(SessId, Version,
ConnectionStates0, Renegotiation),
State1 = server_hello(ServerHello, State0),
case Type of
new ->
- do_server_hello(ServerHello, State1);
+ new_server_hello(ServerHello, State1);
resumed ->
ConnectionStates1 = State1#state.connection_states,
case ssl_handshake:master_secret(Version, Session,
@@ -1216,9 +1226,9 @@ do_server_hello(Type, #state{negotiated_version = Version,
handle_own_alert(Alert, Version, hello, State1),
{stop, normal, State1}
end
- end;
+ end.
-do_server_hello(#server_hello{cipher_suite = CipherSuite,
+new_server_hello(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression,
session_id = SessionId},
#state{session = Session0,
@@ -1343,7 +1353,7 @@ certify_server(#state{transport_cb = Transport,
key_exchange(#state{role = server, key_algorithm = rsa} = State) ->
State;
key_exchange(#state{role = server, key_algorithm = Algo,
- diffie_hellman_params = Params,
+ diffie_hellman_params = #'DHParameter'{prime = P, base = G} = Params,
private_key = PrivateKey,
connection_states = ConnectionStates0,
negotiated_version = Version,
@@ -1354,7 +1364,7 @@ key_exchange(#state{role = server, key_algorithm = Algo,
when Algo == dhe_dss;
Algo == dhe_rsa ->
- Keys = public_key:gen_key(Params),
+ Keys = crypto:dh_generate_key([crypto:mpint(P), crypto:mpint(G)]),
ConnectionState =
ssl_record:pending_connection_state(ConnectionStates0, read),
SecParams = ConnectionState#connection_state.security_parameters,
@@ -1406,6 +1416,8 @@ key_exchange(#state{role = client,
State#state{connection_states = ConnectionStates1,
tls_handshake_hashes = Hashes1}.
+-spec(rsa_key_exchange/2 :: (_,_) -> no_return()).
+
rsa_key_exchange(PremasterSecret, PublicKeyInfo = {Algorithm, _, _})
when Algorithm == ?rsaEncryption;
Algorithm == ?md2WithRSAEncryption;
@@ -1536,7 +1548,7 @@ verify_dh_params(Signed, Hashes, {?rsaEncryption, PubKey, _PubKeyParams}) ->
false
end;
verify_dh_params(Signed, Hash, {?'id-dsa', PublicKey, PublicKeyParams}) ->
- public_key:verify_signature(Hash, none, Signed, PublicKey, PublicKeyParams).
+ public_key:verify(Hash, none, Signed, {PublicKey, PublicKeyParams}).
cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) ->
@@ -1563,7 +1575,7 @@ encode_change_cipher(#change_cipher_spec{}, Version, ConnectionStates) ->
ssl_record:encode_change_cipher_spec(Version, ConnectionStates).
encode_handshake(HandshakeRec, Version, ConnectionStates, Hashes) ->
- encode_handshake(HandshakeRec, undefined, Version,
+ encode_handshake(HandshakeRec, null, Version,
ConnectionStates, Hashes).
encode_handshake(HandshakeRec, SigAlg, Version, ConnectionStates0, Hashes0) ->
@@ -1726,11 +1738,13 @@ format_packet_error(#socket_options{active = _, mode = Mode}, Data) ->
format_reply(binary, _, N, Data) when N > 0 -> % Header mode
header(N, Data);
-format_reply(binary, _, _, Data) -> Data;
-format_reply(list, Packet, _, Data) when is_integer(Packet); Packet == raw ->
- binary_to_list(Data);
+format_reply(binary, _, _, Data) ->
+ Data;
+format_reply(list, Packet, _, Data)
+ when Packet == http; Packet == {http, headers}; Packet == http_bin; Packet == {http_bin, headers} ->
+ Data;
format_reply(list, _,_, Data) ->
- Data.
+ binary_to_list(Data).
header(0, <<>>) ->
<<>>;
@@ -2154,7 +2168,7 @@ renegotiate(#state{role = server,
negotiated_version = Version,
connection_states = ConnectionStates0} = State0) ->
HelloRequest = ssl_handshake:hello_request(),
- Frag = ssl_handshake:encode_handshake(HelloRequest, Version, undefined),
+ Frag = ssl_handshake:encode_handshake(HelloRequest, Version, null),
Hs0 = ssl_handshake:init_hashes(),
{BinMsg, ConnectionStates} =
ssl_record:encode_handshake(Frag, Version, ConnectionStates0),
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index fcc30f6137..3d831eae02 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -42,8 +42,10 @@
encode_handshake/3, init_hashes/0,
update_hashes/2, decrypt_premaster_secret/2]).
--type tls_handshake() :: #client_hello{} | #server_hello{} | #server_hello_done{} |
-#certificate{} | #client_key_exchange{} | #finished{} | #certificate_verify{}.
+-type tls_handshake() :: #client_hello{} | #server_hello{} |
+ #server_hello_done{} | #certificate{} | #certificate_request{} |
+ #client_key_exchange{} | #finished{} | #certificate_verify{} |
+ #hello_request{}.
%%====================================================================
%% Internal application API
@@ -64,7 +66,7 @@ client_hello(Host, Port, ConnectionStates, #ssl_options{versions = Versions,
Version = ssl_record:highest_protocol_version(lists:map(Fun, Versions)),
Pending = ssl_record:pending_connection_state(ConnectionStates, read),
SecParams = Pending#connection_state.security_parameters,
- Ciphers = available_suites(Cert, UserSuites, Version),
+ Ciphers = available_suites(UserSuites, Version),
Id = ssl_manager:client_session_id(Host, Port, SslOpts),
@@ -110,7 +112,7 @@ hello_request() ->
#connection_states{} | {port_num(), #session{}, cache_ref(),
atom(), #connection_states{}, binary()},
boolean()) -> {tls_version(), session_id(), #connection_states{}}|
- {tls_version(), {resumed | new, session_id()},
+ {tls_version(), {resumed | new, #session{}},
#connection_states{}} | #alert{}.
%%
%% Description: Handles a recieved hello message
@@ -232,7 +234,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbRef,
end.
%%--------------------------------------------------------------------
--spec certificate(der_cert(), term(), client | server) -> #certificate{}.
+-spec certificate(der_cert(), term(), client | server) -> #certificate{} | #alert{}.
%%
%% Description: Creates a certificate message.
%%--------------------------------------------------------------------
@@ -260,8 +262,8 @@ certificate(OwnCert, CertDbRef, server) ->
%%--------------------------------------------------------------------
-spec client_certificate_verify(undefined | der_cert(), binary(),
tls_version(), key_algo(), private_key(),
- {binary(), binary()}) ->
- #certificate_verify{} | ignore.
+ {{binary(), binary()},{binary(), binary()}}) ->
+ #certificate_verify{} | ignore | #alert{}.
%%
%% Description: Creates a certificate_verify message, called by the client.
%%--------------------------------------------------------------------
@@ -283,9 +285,9 @@ client_certificate_verify(OwnCert, MasterSecret, Version, Algorithm,
end.
%%--------------------------------------------------------------------
--spec certificate_verify(binary(), public_key_info(), tls_version(),
- binary(), key_algo(),
- {binary(), binary()}) -> valid | #alert{}.
+%% -spec certificate_verify(binary(), public_key_info(), tls_version(),
+%% binary(), key_algo(),
+%% {_, {binary(), binary()}}) -> valid | #alert{}.
%%
%% Description: Checks that the certificate_verify message is valid.
%%--------------------------------------------------------------------
@@ -306,7 +308,7 @@ certificate_verify(Signature, {_, PublicKey, PublicKeyParams}, Version,
MasterSecret, dhe_dss = Algorithm, {_, Hashes0}) ->
Hashes = calc_certificate_verify(Version, MasterSecret,
Algorithm, Hashes0),
- case public_key:verify_signature(Hashes, none, Signature, PublicKey, PublicKeyParams) of
+ case public_key:verify(Hashes, none, Signature, {PublicKey, PublicKeyParams}) of
true ->
valid;
false ->
@@ -335,7 +337,7 @@ certificate_request(ConnectionStates, CertDbRef) ->
-spec key_exchange(client | server,
{premaster_secret, binary(), public_key_info()} |
{dh, binary()} |
- {dh, binary(), #'DHParameter'{}, key_algo(),
+ {dh, {binary(), binary()}, #'DHParameter'{}, key_algo(),
binary(), binary(), private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
@@ -412,7 +414,7 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
end.
%%--------------------------------------------------------------------
--spec finished(tls_version(), client | server, binary(), {binary(), binary()}) ->
+-spec finished(tls_version(), client | server, binary(), {{binary(), binary()},_}) ->
#finished{}.
%%
%% Description: Creates a handshake finished message
@@ -423,7 +425,7 @@ finished(Version, Role, MasterSecret, {Hashes, _}) -> % use the current hashes
%%--------------------------------------------------------------------
-spec verify_connection(tls_version(), #finished{}, client | server, binary(),
- {binary(), binary()}) -> verified | #alert{}.
+ {_, {binary(), binary()}}) -> verified | #alert{}.
%%
%% Description: Checks the ssl handshake finished message to verify
%% the connection.
@@ -448,7 +450,7 @@ server_hello_done() ->
#server_hello_done{}.
%%--------------------------------------------------------------------
--spec encode_handshake(tls_handshake(), tls_version(), key_algo()) -> binary().
+-spec encode_handshake(tls_handshake(), tls_version(), key_algo()) -> iolist().
%%
%% Description: Encode a handshake packet to binary
%%--------------------------------------------------------------------
@@ -459,8 +461,8 @@ encode_handshake(Package, Version, KeyAlg) ->
[MsgType, ?uint24(Len), Bin].
%%--------------------------------------------------------------------
--spec get_tls_handshake(binary(), binary(), key_algo(), tls_version()) ->
- {[tls_handshake()], [binary()], binary()}.
+-spec get_tls_handshake(binary(), binary() | iolist(), key_algo(), tls_version()) ->
+ {[tls_handshake()], binary()}.
%%
%% Description: Given buffered and new data from ssl_record, collects
%% and returns it as a list of handshake messages, also returns leftover
@@ -524,13 +526,16 @@ select_session(Hello, Port, Session, Version,
{resumed, CacheCb:lookup(Cache, {Port, SessionId})}
end.
-available_suites(Cert, UserSuites, Version) ->
+available_suites(UserSuites, Version) ->
case UserSuites of
[] ->
- ssl_cipher:filter(Cert, ssl_cipher:suites(Version));
+ ssl_cipher:suites(Version);
_ ->
- ssl_cipher:filter(Cert, UserSuites)
+ UserSuites
end.
+
+available_suites(ServerCert, UserSuites, Version) ->
+ ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version)).
cipher_suites(Suites, false) ->
[?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites];
@@ -1042,9 +1047,10 @@ certificate_authorities(CertDbRef) ->
Authorities = certificate_authorities_from_db(CertDbRef),
Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
- Subj = public_key:pkix_transform(OTPSubj, encode),
- {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj),
- DNEncodedBin = iolist_to_binary(DNEncoded),
+ DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
+ %%Subj = public_key:pkix_transform(OTPSubj, encode),
+ %% {ok, DNEncoded} = 'OTP-PUB-KEY':encode('Name', Subj),
+ %% DNEncodedBin = iolist_to_binary(DNEncoded),
DNEncodedLen = byte_size(DNEncodedBin),
<<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
end,
@@ -1068,7 +1074,7 @@ digitally_signed(Hash, #'RSAPrivateKey'{} = Key) ->
public_key:encrypt_private(Hash, Key,
[{rsa_pad, rsa_pkcs1_padding}]);
digitally_signed(Hash, #'DSAPrivateKey'{} = Key) ->
- public_key:sign(none, Hash, Key).
+ public_key:sign(Hash, none, Key).
calc_master_secret({3,0}, PremasterSecret, ClientRandom, ServerRandom) ->
ssl_ssl3:master_secret(PremasterSecret, ClientRandom, ServerRandom);
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index ddace02dea..337403531e 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -96,12 +96,12 @@
-type from() :: term().
-type host() :: string() | tuple().
-type port_num() :: integer().
--type session_id() :: binary().
+-type session_id() :: 0 | binary().
-type tls_version() :: {integer(), integer()}.
-type tls_atom_version() :: sslv3 | tlsv1.
-type cache_ref() :: term().
-type certdb_ref() :: term().
--type key_algo() :: rsa | dhe_rsa | dhe_dss.
+-type key_algo() :: null | rsa | dhe_rsa | dhe_dss.
-type enum_algo() :: integer().
-type public_key() :: #'RSAPublicKey'{} | integer().
-type public_key_params() :: #'Dss-Parms'{} | term().
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index af30f78dbf..459dcefb79 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -29,7 +29,8 @@
%% Internal application API
-export([start_link/1,
connection_init/2, cache_pem_file/1,
- lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3, server_session_id/3,
+ lookup_trusted_cert/3, issuer_candidate/1, client_session_id/3,
+ server_session_id/3,
register_session/2, register_session/3, invalidate_session/2,
invalidate_session/3]).
@@ -88,14 +89,17 @@ cache_pem_file(File) ->
end.
%%--------------------------------------------------------------------
-spec lookup_trusted_cert(reference(), serialnumber(), issuer()) ->
- {der_cert(), #'OTPCertificate'{}}.
+ undefined |
+ {ok, {der_cert(), #'OTPCertificate'{}}}.
%%
-%% Description: Lookup the trusted cert with Key = {reference(), serialnumber(), issuer()}.
-%%--------------------------------------------------------------------
+%% Description: Lookup the trusted cert with Key = {reference(),
+%% serialnumber(), issuer()}.
+%% --------------------------------------------------------------------
lookup_trusted_cert(Ref, SerialNumber, Issuer) ->
ssl_certificate_db:lookup_trusted_cert(Ref, SerialNumber, Issuer).
%%--------------------------------------------------------------------
--spec issuer_candidate(cert_key()) -> {cert_key(), der_cert()} | no_more_candidates.
+-spec issuer_candidate(cert_key() | no_candidate) ->
+ {cert_key(), {der_cert(), #'OTPCertificate'{}}} | no_more_candidates.
%%
%% Description: Return next issuer candidate.
%%--------------------------------------------------------------------
@@ -143,8 +147,9 @@ invalidate_session(Port, Session) ->
%%====================================================================
%%--------------------------------------------------------------------
--spec init(list()) -> {ok, #state{}} | {ok, #state{}, timeout()} |
- ignore | {stop, term()}.
+-spec init(list()) -> {ok, #state{}}.
+%% Possible return values not used now.
+%% | {ok, #state{}, timeout()} | ignore | {stop, term()}.
%%
%% Description: Initiates the server
%%--------------------------------------------------------------------
@@ -164,12 +169,13 @@ init([Opts]) ->
session_validation_timer = Timer}}.
%%--------------------------------------------------------------------
--spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}} |
- {reply, reply(), #state{}, timeout()} |
- {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), reply(), #state{}} |
- {stop, reason(), #state{}}.
+-spec handle_call(msg(), from(), #state{}) -> {reply, reply(), #state{}}.
+%% Possible return values not used now.
+%% {reply, reply(), #state{}, timeout()} |
+%% {noreply, #state{}} |
+%% {noreply, #state{}, timeout()} |
+%% {stop, reason(), reply(), #state{}} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling call messages
%%--------------------------------------------------------------------
@@ -216,9 +222,10 @@ handle_call({{cache_pem, File},Pid}, _, State = #state{certificate_db = Db}) ->
{reply, {error, Reason}, State}
end.
%%--------------------------------------------------------------------
--spec handle_cast(msg(), #state{}) -> {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), #state{}}.
+-spec handle_cast(msg(), #state{}) -> {noreply, #state{}}.
+%% Possible return values not used now.
+%% | {noreply, #state{}, timeout()} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling cast messages
%%--------------------------------------------------------------------
@@ -253,9 +260,10 @@ handle_cast({invalidate_session, Port, #session{session_id = ID}},
{noreply, State}.
%%--------------------------------------------------------------------
--spec handle_info(msg(), #state{}) -> {noreply, #state{}} |
- {noreply, #state{}, timeout()} |
- {stop, reason(), #state{}}.
+-spec handle_info(msg(), #state{}) -> {noreply, #state{}}.
+%% Possible return values not used now.
+%% |{noreply, #state{}, timeout()} |
+%% {stop, reason(), #state{}}.
%%
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 90615c22a1..acd0d49c19 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -149,7 +149,7 @@ set_mac_secret(ReadMacSecret, WriteMacSecret,
%%--------------------------------------------------------------------
--spec set_master_secret(binary(), #connection_state{}) -> #connection_states{}.
+-spec set_master_secret(binary(), #connection_states{}) -> #connection_states{}.
%%
%% Description: Set master_secret in pending connection states
%%--------------------------------------------------------------------
@@ -306,7 +306,7 @@ set_pending_cipher_state(#connection_states{pending_read = Read,
pending_write = Write#connection_state{cipher_state = ClientState}}.
%%--------------------------------------------------------------------
--spec get_tls_records(binary(), binary()) -> {[binary()], binary()}.
+-spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from TCP, packs up a records
%% and returns it as a list of tls_compressed binaries also returns leftover
@@ -372,7 +372,8 @@ get_tls_records_aux(Data, Acc) ->
{lists:reverse(Acc), Data}.
%%--------------------------------------------------------------------
--spec protocol_version(tls_atom_version()) -> tls_version().
+-spec protocol_version(tls_atom_version() | tls_version()) ->
+ tls_version() | tls_atom_version().
%%
%% Description: Creates a protocol version record from a version atom
%% or vice versa.
@@ -467,7 +468,7 @@ is_acceptable_version(_) ->
false.
%%--------------------------------------------------------------------
--spec compressions() -> binary().
+-spec compressions() -> [binary()].
%%
%% Description: return a list of compressions supported (currently none)
%%--------------------------------------------------------------------
@@ -476,7 +477,7 @@ compressions() ->
%%--------------------------------------------------------------------
-spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
- {#ssl_tls{}, #connection_states{}}.
+ {#ssl_tls{}, #connection_states{}}| #alert{}.
%%
%% Description: Decode cipher text
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index e9755cb0e1..6db13e5b7a 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -35,7 +35,7 @@
-type seconds() :: integer().
%%--------------------------------------------------------------------
--spec is_new(binary(), binary()) -> boolean().
+-spec is_new(session_id(), session_id()) -> boolean().
%%
%% Description: Checks if the session id decided by the server is a
%% new or resumed sesion id.
diff --git a/lib/ssl/src/ssl_ssl3.erl b/lib/ssl/src/ssl_ssl3.erl
index 375adf263a..1add203fb0 100644
--- a/lib/ssl/src/ssl_ssl3.erl
+++ b/lib/ssl/src/ssl_ssl3.erl
@@ -121,9 +121,10 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, Length, Fragment) ->
?DBG_HEX(Mac),
Mac.
--spec setup_keys(binary(), binary(), binary(), binary(),
- integer(), integer(), binary()) -> {binary(), binary(), binary(),
- binary(), binary(), binary()}.
+-spec setup_keys(binary(), binary(), binary(),
+ integer(), integer(), term(), integer()) ->
+ {binary(), binary(), binary(),
+ binary(), binary(), binary()}.
setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
KeyBlock = generate_keyblock(MasterSecret, ServerRandom, ClientRandom,
diff --git a/lib/ssl/src/ssl_sup.erl b/lib/ssl/src/ssl_sup.erl
index b7cb5c3ab3..316ed8a4e9 100644
--- a/lib/ssl/src/ssl_sup.erl
+++ b/lib/ssl/src/ssl_sup.erl
@@ -32,14 +32,17 @@
%%%=========================================================================
%%% API
%%%=========================================================================
+
+-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
+
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
-%% init([]) -> {ok, {SupFlags, [ChildSpec]}}
-%%
+-spec init([]) -> {ok, {SupFlags :: tuple(), [ChildSpec :: tuple()]}}.
+
init([]) ->
%% OLD ssl - moved start to ssl.erl only if old
%% ssl is acctualy run!