aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/public_key/doc/src/notes.xml49
-rw-r--r--lib/public_key/include/public_key.hrl2
-rw-r--r--lib/public_key/src/pubkey_cert.erl15
-rw-r--r--lib/public_key/src/public_key.appup.src44
-rw-r--r--lib/public_key/src/public_key.erl19
-rw-r--r--lib/public_key/test/public_key_SUITE.erl8
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml42
-rw-r--r--lib/ssl/doc/src/ssl.xml33
-rw-r--r--lib/ssl/src/ssl.appup.src27
-rw-r--r--lib/ssl/src/ssl.erl12
-rw-r--r--lib/ssl/src/ssl_certificate.erl16
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl19
-rw-r--r--lib/ssl/src/ssl_handshake.erl2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl6
-rw-r--r--lib/ssl/vsn.mk3
16 files changed, 185 insertions, 114 deletions
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index baa0e6c464..ca32063624 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -34,6 +34,55 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 0.9</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Updated ssl to ignore CA certs that violate the asn1-spec
+ for a certificate, and updated public key asn1 spec to
+ handle inherited DSS-params.</p>
+ <p>
+ Own Id: OTP-7884</p>
+ </item>
+ <item>
+ <p>
+ Changed ssl implementation to retain backwards
+ compatibility for old option {verify, 0} that shall be
+ equivalent to {verify, verify_none}, also separate the
+ cases unknown ca and selfsigned peer cert, and restored
+ return value of deprecated function
+ public_key:pem_to_der/1.</p>
+ <p>
+ Own Id: OTP-8858</p>
+ </item>
+ <item>
+ <p>
+ Better handling of v1 and v2 certificates. V1 and v2
+ certificates does not have any extensions so then
+ validate_extensions should just accept that there are
+ none and not end up in missing_basic_constraints clause.</p>
+ <p>
+ Own Id: OTP-8867</p>
+ </item>
+ <item>
+ <p>
+ Changed the verify fun so that it differentiate between
+ the peer certificate and CA certificates by using
+ valid_peer or valid as the second argument to the verify
+ fun. It may not always be trivial or even possible to
+ know when the peer certificate is reached otherwise.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8873</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 0.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index a16eb10fe6..4950597fb5 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -34,6 +34,8 @@
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, []}).
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index e704c168f1..570f44e530 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -223,10 +223,15 @@ validate_revoked_status(_OtpCert, UserState, _VerifyFun) ->
%%--------------------------------------------------------------------
validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- validate_extensions(OtpCert, Extensions, ValidationState, no_basic_constraint,
- is_self_signed(OtpCert), UserState, VerifyFun).
-
+ case TBSCert#'OTPTBSCertificate'.version of
+ N when N >= 3 ->
+ Extensions = TBSCert#'OTPTBSCertificate'.extensions,
+ validate_extensions(OtpCert, Extensions,
+ ValidationState, no_basic_constraint,
+ is_self_signed(OtpCert), UserState, VerifyFun);
+ _ -> %% Extensions not present in versions 1 & 2
+ {ValidationState, UserState}
+ end.
%%--------------------------------------------------------------------
-spec normalize_general_name({rdnSequence, term()}) -> {rdnSequence, term()}.
%%
@@ -291,7 +296,7 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
%%--------------------------------------------------------------------
-spec verify_fun(#'OTPTBSCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
- valid, term(), fun()) -> term().
+ valid | valid_peer, term(), fun()) -> term().
%%
%% Description: Gives the user application the opportunity handle path
%% validation errors and unknown extensions and optional do other
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index c9d15b8747..0f9f62d2f6 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,62 +1,24 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"0.7",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
{update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.6",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
}
],
[
- {"0.7",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
{update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.6",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
- }
+ }
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 9c7817fa8e..d514b9a3aa 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -437,7 +437,7 @@ pkix_normalize_name(Issuer) ->
pubkey_cert:normalize_general_name(Issuer).
%%--------------------------------------------------------------------
--spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | unknown_ca,
+-spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | atom(),
CertChain :: [der_encoded()] ,
Options :: list()) ->
{ok, {PublicKeyInfo :: term(),
@@ -445,11 +445,11 @@ pkix_normalize_name(Issuer) ->
{error, {bad_cert, Reason :: term()}}.
%% Description: Performs a basic path validation according to RFC 5280.
%%--------------------------------------------------------------------
-pkix_path_validation(unknown_ca, [Cert | Chain], Options0) ->
+pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
{VerifyFun, Userstat0} =
proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN),
Otpcert = pkix_decode_cert(Cert, otp),
- Reason = {bad_cert, unknown_ca},
+ Reason = {bad_cert, PathErr},
try VerifyFun(Otpcert, Reason, Userstat0) of
{valid, Userstate} ->
Options = proplists:delete(verify_fun, Options0),
@@ -557,9 +557,16 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
%% We want the key_usage extension to be checked before we validate
%% the signature.
- UserState0 = pubkey_cert:validate_signature(OtpCert, DerCert,
+ UserState6 = pubkey_cert:validate_signature(OtpCert, DerCert,
Key, KeyParams, UserState5, VerifyFun),
- UserState = pubkey_cert:verify_fun(OtpCert, valid, UserState0, VerifyFun),
+ UserState = case Last of
+ false ->
+ pubkey_cert:verify_fun(OtpCert, valid, UserState6, VerifyFun);
+ true ->
+ pubkey_cert:verify_fun(OtpCert, valid_peer,
+ UserState6, VerifyFun)
+ end,
+
ValidationState =
ValidationState1#path_validation_state{user_state = UserState},
@@ -576,7 +583,7 @@ sized_binary(List) ->
%%--------------------------------------------------------------------
pem_to_der(CertSource) ->
{ok, Bin} = file:read_file(CertSource),
- pubkey_pem:decode(Bin).
+ {ok, pubkey_pem:decode(Bin)}.
decode_private_key(KeyInfo) ->
decode_private_key(KeyInfo, no_passwd).
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index ea6a925139..81e01f3a02 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -379,6 +379,8 @@ pkix_path_validation(Config) when is_list(Config) ->
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, []},
{ok, _} =
@@ -411,11 +413,11 @@ deprecated(suite) ->
[];
deprecated(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
- [DsaKey = {'DSAPrivateKey', _DsaKey, _}] =
+ {ok, [DsaKey = {'DSAPrivateKey', _DsaKey, _}]} =
public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- [RsaKey = {'RSAPrivateKey', _RsaKey,_}] =
+ {ok, [RsaKey = {'RSAPrivateKey', _RsaKey,_}]} =
public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}] =
+ {ok, [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}]} =
public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
{ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index f70209d891..2810942171 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.8
+PUBLIC_KEY_VSN = 0.9
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 5f9e436348..756c0d1b1f 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -31,7 +31,47 @@
<p>This document describes the changes made to the SSL application.
</p>
- <section><title>SSL 4.0.1</title>
+ <section><title>SSL 4.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Updated ssl to ignore CA certs that violate the asn1-spec
+ for a certificate, and updated public key asn1 spec to
+ handle inherited DSS-params.</p>
+ <p>
+ Own Id: OTP-7884</p>
+ </item>
+ <item>
+ <p>
+ Changed ssl implementation to retain backwards
+ compatibility for old option {verify, 0} that shall be
+ equivalent to {verify, verify_none}, also separate the
+ cases unknown ca and selfsigned peer cert, and restored
+ return value of deprecated function
+ public_key:pem_to_der/1.</p>
+ <p>
+ Own Id: OTP-8858</p>
+ </item>
+ <item>
+ <p>
+ Changed the verify fun so that it differentiate between
+ the peer certificate and CA certificates by using
+ valid_peer or valid as the second argument to the verify
+ fun. It may not always be trivial or even possible to
+ know when the peer certificate is reached otherwise.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-8873</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 4.0.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index d5b7253ef3..413703deca 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -202,10 +202,10 @@
<p>The verification fun should be defined as:</p>
<code>
-fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
+fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
{extension, #'Extension'{}}, InitialUserState :: term()) ->
- {valid, UserState :: term()} | {fail, Reason :: term()} |
- {unknown, UserState :: term()}.
+ {valid, UserState :: term()} | {valid_peer, UserState :: term()} |
+ {fail, Reason :: term()} | {unknown, UserState :: term()}.
</code>
<p>The verify fun will be called during the X509-path
@@ -213,10 +213,12 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
application is encountered. Additionally it will be called
when a certificate is considered valid by the path validation
to allow access to each certificate in the path to the user
- application.
+ application. Note that the it will differentiate between
+ the peer certificate and CA certificates by using valid_peer
+ or valid as the second argument to the verify fun.
See
<seealso marker="public_key:application">public_key(3)</seealso>
- for definition of #'OtpCertificate'{} and #'Extension'{}.</p>
+ for definition of #'OTPCertificate'{} and #'Extension'{}.</p>
<p>If the verify callback fun returns {fail, Reason}, the
verification process is immediately stopped and an alert is
@@ -237,21 +239,23 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
- {valid, UserState}
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
end, []}
</code>
<p>The default verify_fun option in verify_none mode:</p>
<code>
-{fun(_,{bad_cert, unknown_ca}, UserState) ->
+{fun(_,{bad_cert, _}, UserState) ->
{valid, UserState};
- (_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
- {valid, UserState}
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
end, []}
</code>
@@ -267,13 +271,14 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title>
- <p>Option described here are client specific or has a slightly different
+ <p>Options described here are client specific or has a slightly different
meaning in the client than in the server.</p>
<taglist>
<tag>{verify, verify_type()}</tag>
- <item> In verify_none mode the x509-path validation error {bad_cert, unknown_ca}
- will automatically be accepted. See also the verify_fun option.
+ <item> In verify_none mode the default behavior will be to
+ allow all x509-path validation errors. See also the verify_fun
+ option.
</item>
<tag>{reuse_sessions, boolean()}</tag>
<item>Specifies if client should try to reuse sessions
@@ -286,7 +291,7 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title>
- <p>Option described here are server specific or has a slightly different
+ <p>Options described here are server specific or has a slightly different
meaning in the server than in the client.</p>
<taglist>
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 88cd73be74..f4e6b59b6d 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,32 +1,9 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"4.0", [{restart_application, ssl}]},
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.7", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
],
[
- {"4.0", [{restart_application, ssl}]},
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 12dffb413c..b4437628c3 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -529,17 +529,19 @@ handle_options(Opts0, _Role) ->
ReuseSessionFun = fun(_, _, _, _) -> true end,
- VerifyNoneFun =
- {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ DefaultVerifyNoneFun =
+ {fun(_,{bad_cert, _}, UserState) ->
{valid, UserState};
- (_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, []},
+ VerifyNoneFun = handle_option(verify_fun, Opts, DefaultVerifyNoneFun),
+
UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false),
UserVerifyFun = handle_option(verify_fun, Opts, undefined),
CaCerts = handle_option(cacerts, Opts, undefined),
@@ -635,6 +637,8 @@ validate_option(verify_fun, Fun) when is_function(Fun) ->
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, Fun};
validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) ->
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 206024315e..a4c54afb27 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -57,30 +57,32 @@
trusted_cert_and_path(CertChain, CertDbRef) ->
Path = [Cert | _] = lists:reverse(CertChain),
OtpCert = public_key:pkix_decode_cert(Cert, otp),
- IssuerID =
+ SignedAndIssuerID =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
{ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self),
- IssuerId;
+ {self, IssuerId};
false ->
case public_key:pkix_issuer_id(OtpCert, other) of
{ok, IssuerId} ->
- IssuerId;
+ {other, IssuerId};
{error, issuer_not_found} ->
case find_issuer(OtpCert, no_candidate) of
{ok, IssuerId} ->
- IssuerId;
+ {other, IssuerId};
Other ->
Other
end
end
end,
- case IssuerID of
+ case SignedAndIssuerID of
{error, issuer_not_found} ->
%% The root CA was not sent and can not be found.
{unknown_ca, Path};
- {SerialNr, Issuer} ->
+ {self, _} when length(Path) == 1 ->
+ {selfsigned_peer, Path};
+ {_ ,{SerialNr, Issuer}} ->
case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of
{ok, {BinCert,_}} ->
{BinCert, Path};
@@ -129,6 +131,8 @@ validate_extension(_, {bad_cert, _} = Reason, _) ->
validate_extension(_, {extension, _}, Role) ->
{unknown, Role};
validate_extension(_, valid, Role) ->
+ {valid, Role};
+validate_extension(_, valid_peer, Role) ->
{valid, Role}.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index 86477f369d..7d50c30d47 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -216,9 +216,16 @@ add_certs_from_file(File, Ref, CertsDb) ->
[Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries].
add_certs(Cert, Ref, CertsDb) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- Issuer = public_key:pkix_normalize_name(
- TBSCertificate#'OTPTBSCertificate'.issuer),
- insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb).
+ try ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
+ Issuer = public_key:pkix_normalize_name(
+ TBSCertificate#'OTPTBSCertificate'.issuer),
+ insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb)
+ catch
+ error:_ ->
+ Report = io_lib:format("SSL WARNING: Ignoring a CA cert as "
+ "it could not be correctly decoded.~n", []),
+ error_logger:info_report(Report)
+ end.
+
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 99bc47f04b..b9b1ccb134 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -496,6 +496,8 @@ path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
path_validation_alert({bad_cert, cert_revoked}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
+path_validation_alert({bad_cert, selfsigned_peer}) ->
+ ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
path_validation_alert({bad_cert, unknown_ca}) ->
?ALERT_REC(?FATAL, ?UNKNOWN_CA);
path_validation_alert(_) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 3cb9337775..fade67f3ba 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -2857,11 +2857,13 @@ unknown_server_ca_fail(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- FunAndState = {fun(_,{bad_cert, _} = Reason, _) ->
+ FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) ->
{fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, [test_to_update_user_state | UserState]};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, []},
@@ -2930,6 +2932,8 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
{valid, UserState}
end, []},
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 709a089892..30a0a3b3f7 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1,2 @@
-SSL_VSN = 4.0.1
+
+SSL_VSN = 4.1