From 59ec0761d69608a6d4be2db1967e71efdb9f535d Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 19 Aug 2016 08:46:48 -0400 Subject: Add option to bypass SSL PEM cache The current SSL implementation has a PEM cache running through the ssl manager process, whose primary role is caching CA chains from files on disk. This is intended as a way to save on disk operation when the requested certificates are often the same, and those cache values are both time-bound and reference-counted. The code path also includes caching the Erlang-formatted certificate as decoded by the public_key application The same code path is used for DER-encoded certificates, which are passed in memory and do not require file access. These certificates are cached, but not reference-counted and also not shared across connections. For heavy usage of DER-encoded certificates, the PEM cache becomes a central bottleneck for a server, forcing the decoding of every one of them individually through a single critical process. It is also not clear if the cache remains useful for disk certificates in all cases. This commit adds a configuration variable for the ssl application (bypass_pem_cache = true | false) which allows to open files and decode certificates in the calling connection process rather than the manager. When this action takes place, the operations to cache and return data are replaced to strictly return data. To provide a transparent behaviour, the 'CacheDbRef' used to keep track of the certificates in the cache is replaced by the certificates itself, and all further lookup functions or folds can be done locally. This has proven under benchmark to more than triple the performance of the SSL application under load (once the session cache had also been disabled). --- lib/ssl/src/ssl_certificate.erl | 34 ++++++++++++++------- lib/ssl/src/ssl_handshake.erl | 9 ++++-- lib/ssl/src/ssl_manager.erl | 43 ++++++++++++++++++++------ lib/ssl/src/ssl_pkix_db.erl | 67 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 127 insertions(+), 26 deletions(-) diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index 3ec3f50e05..f359655d85 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -64,7 +64,7 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) - {ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self), {self, IssuerId}; false -> - other_issuer(OtpCert, BinCert, CertDbHandle) + other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) end, case SignedAndIssuerID of @@ -200,7 +200,7 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) -> {_, true = SelfSigned} -> certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned); {{error, issuer_not_found}, SelfSigned} -> - case find_issuer(OtpCert, BinCert, CertDbHandle) of + case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) of {ok, {SerialNr, Issuer}} -> certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned); @@ -232,7 +232,7 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned {ok, undefined, lists:reverse(Chain)} end. -find_issuer(OtpCert, BinCert, CertDbHandle) -> +find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) -> IsIssuerFun = fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) -> case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of @@ -250,12 +250,24 @@ find_issuer(OtpCert, BinCert, CertDbHandle) -> Acc end, - try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of - issuer_not_found -> - {error, issuer_not_found} - catch - {ok, _IssuerId} = Return -> - Return + if is_reference(CertsDbRef) -> % actual DB exists + try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of + issuer_not_found -> + {error, issuer_not_found} + catch + {ok, _IssuerId} = Return -> + Return + end; + is_tuple(CertsDbRef), element(1,CertsDbRef) =:= extracted -> % cache bypass byproduct + {extracted, CertsData} = CertsDbRef, + DB = [Entry || {decoded, Entry} <- CertsData], + try lists:foldl(IsIssuerFun, issuer_not_found, DB) of + issuer_not_found -> + {error, issuer_not_found} + catch + {ok, _IssuerId} = Return -> + Return + end end. is_valid_extkey_usage(KeyUse, client) -> @@ -281,12 +293,12 @@ public_key(#'OTPSubjectPublicKeyInfo'{algorithm = #'PublicKeyAlgorithm'{algorith subjectPublicKey = Key}) -> {Key, Params}. -other_issuer(OtpCert, BinCert, CertDbHandle) -> +other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) -> case public_key:pkix_issuer_id(OtpCert, other) of {ok, IssuerId} -> {other, IssuerId}; {error, issuer_not_found} -> - case find_issuer(OtpCert, BinCert, CertDbHandle) of + case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) of {ok, IssuerId} -> {other, IssuerId}; Other -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 081efda768..288244ef36 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1219,13 +1219,18 @@ certificate_authorities(CertDbHandle, CertDbRef) -> end, list_to_binary([Enc(Cert) || {_, Cert} <- Authorities]). -certificate_authorities_from_db(CertDbHandle, CertDbRef) -> +certificate_authorities_from_db(CertDbHandle, CertDbRef) when is_reference(CertDbRef) -> ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef -> [Cert | Acc]; (_, Acc) -> Acc end, - ssl_pkix_db:foldl(ConnectionCerts, [], CertDbHandle). + ssl_pkix_db:foldl(ConnectionCerts, [], CertDbHandle); +certificate_authorities_from_db(_CertDbHandle, {extracted, CertDbData}) -> + %% Cache disabled, Ref contains data + lists:foldl(fun({decoded, {_Key,Cert}}, Acc) -> [Cert | Acc] end, + [], CertDbData). + %%-------------Extension handling -------------------------------- diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index c7dcbaabe9..5bd9521de7 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -115,13 +115,25 @@ start_link_dist(Opts) -> %% Description: Do necessary initializations for a new connection. %%-------------------------------------------------------------------- connection_init({der, _} = Trustedcerts, Role, CRLCache) -> - call({connection_init, Trustedcerts, Role, CRLCache}); + case bypass_pem_cache() of + true -> + {ok, Extracted} = ssl_pkix_db:extract_trusted_certs(Trustedcerts), + call({connection_init, Extracted, Role, CRLCache}); + false -> + call({connection_init, Trustedcerts, Role, CRLCache}) + end; connection_init(<<>> = Trustedcerts, Role, CRLCache) -> call({connection_init, Trustedcerts, Role, CRLCache}); connection_init(Trustedcerts, Role, CRLCache) -> - call({connection_init, Trustedcerts, Role, CRLCache}). + case bypass_pem_cache() of + true -> + {ok, Extracted} = ssl_pkix_db:extract_trusted_certs(Trustedcerts), + call({connection_init, Extracted, Role, CRLCache}); + false -> + call({connection_init, Trustedcerts, Role, CRLCache}) + end. %%-------------------------------------------------------------------- -spec cache_pem_file(binary(), term()) -> {ok, term()} | {error, reason()}. @@ -129,13 +141,18 @@ connection_init(Trustedcerts, Role, CRLCache) -> %% Description: Cache a pem file and return its content. %%-------------------------------------------------------------------- cache_pem_file(File, DbHandle) -> - case ssl_pkix_db:lookup_cached_pem(DbHandle, File) of - [{Content,_}] -> - {ok, Content}; - [Content] -> - {ok, Content}; - undefined -> - call({cache_pem, File}) + case bypass_pem_cache() of + true -> + ssl_pkix_db:decode_pem_file(File); + false -> + case ssl_pkix_db:lookup_cached_pem(DbHandle, File) of + [{Content,_}] -> + {ok, Content}; + [Content] -> + {ok, Content}; + undefined -> + call({cache_pem, File}) + end end. %%-------------------------------------------------------------------- @@ -506,6 +523,14 @@ delay_time() -> ?CLEAN_SESSION_DB end. +bypass_pem_cache() -> + case application:get_env(ssl, bypass_pem_cache) of + {ok, Bool} when is_boolean(Bool) -> + Bool; + _ -> + false + end. + max_session_cache_size(CacheType) -> case application:get_env(ssl, CacheType) of {ok, Size} when is_integer(Size) -> diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl index b16903d7c7..0006ce14d9 100644 --- a/lib/ssl/src/ssl_pkix_db.erl +++ b/lib/ssl/src/ssl_pkix_db.erl @@ -29,10 +29,11 @@ -include_lib("kernel/include/file.hrl"). -export([create/0, add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3, + extract_trusted_certs/1, remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1, ref_count/3, lookup_trusted_cert/4, foldl/3, select_cert_by_issuer/2, lookup_cached_pem/2, cache_pem_file/2, cache_pem_file/3, - lookup/2]). + decode_pem_file/1, lookup/2]). %%==================================================================== %% Internal application API @@ -82,12 +83,22 @@ remove(Dbs) -> %% . Ref is used as it is specified %% for each connection which certificates are trusted. %%-------------------------------------------------------------------- -lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) -> +lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) when is_reference(Ref) -> case lookup({Ref, SerialNumber, Issuer}, DbHandle) of undefined -> undefined; [Certs] -> {ok, Certs} + end; +lookup_trusted_cert(_DbHandle, {extracted,Certs}, SerialNumber, Issuer) -> + try + [throw(Cert) + || {decoded, {{_Ref,CertSerial,CertIssuer}, Cert}} <- Certs, + CertSerial =:= SerialNumber, CertIssuer =:= Issuer], + undefined + catch + Cert -> + {ok, Cert} end. lookup_cached_pem([_, _, PemChache | _], File) -> @@ -103,6 +114,9 @@ lookup_cached_pem(PemChache, File) -> %% runtime database. Returns Ref that should be handed to lookup_trusted_cert %% together with the cert serialnumber and issuer. %%-------------------------------------------------------------------- +add_trusted_certs(_Pid, {extracted, _} = Certs, _) -> + {ok, Certs}; + add_trusted_certs(_Pid, {der, DerList}, [CertDb, _,_ | _]) -> NewRef = make_ref(), add_certs_from_der(DerList, NewRef, CertDb), @@ -122,6 +136,21 @@ add_trusted_certs(_Pid, File, [CertsDb, RefDb, PemChache | _] = Db) -> undefined -> new_trusted_cert_entry(File, Db) end. + +extract_trusted_certs({der, DerList}) -> + {ok, {extracted, certs_from_der(DerList)}}; +extract_trusted_certs(File) -> + case file:read_file(File) of + {ok, PemBin} -> + Content = public_key:pem_decode(PemBin), + DerList = [Cert || {'Certificate', Cert, not_encrypted} <- Content], + {ok, {extracted, certs_from_der(DerList)}}; + Error -> + %% Have to simulate a failure happening in a server for + %% external handlers. + {error, {badmatch, Error}} + end. + %%-------------------------------------------------------------------- %% %% Description: Cache file as binary in DB @@ -141,6 +170,18 @@ cache_pem_file(Ref, File, [_CertsDb, _RefDb, PemChache| _]) -> insert(File, {Content, Ref}, PemChache), {ok, Content}. +-spec decode_pem_file(binary()) -> {ok, term()}. +decode_pem_file(File) -> + case file:read_file(File) of + {ok, PemBin} -> + Content = public_key:pem_decode(PemBin), + {ok, Content}; + Error -> + %% Have to simulate a failure happening in a server for + %% external handlers. + {error, {badmatch, Error}} + end. + %%-------------------------------------------------------------------- -spec remove_trusted_certs(reference(), db_handle()) -> ok. %% @@ -203,6 +244,8 @@ select_cert_by_issuer(Cache, Issuer) -> %% %% Description: Updates a reference counter in a . %%-------------------------------------------------------------------- +ref_count({extracted, _}, _Db, _N) -> + not_cached; ref_count(Key, Db, N) -> ets:update_counter(Db,Key,N). @@ -248,23 +291,39 @@ add_certs_from_der(DerList, Ref, CertsDb) -> [Add(Cert) || Cert <- DerList], ok. +certs_from_der(DerList) -> + Ref = make_ref(), + [Decoded || Cert <- DerList, + Decoded <- [decode_certs(Ref, Cert)], + Decoded =/= undefined]. + add_certs_from_pem(PemEntries, Ref, CertsDb) -> Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end, [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries], ok. add_certs(Cert, Ref, CertsDb) -> + try + {decoded, {Key, Val}} = decode_certs(Ref, Cert), + insert(Key, Val, CertsDb) + catch + error:_ -> + ok + end. + +decode_certs(Ref, Cert) -> 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) + {decoded, {{Ref, SerialNumber, Issuer}, {Cert, ErlCert}}} 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) + error_logger:info_report(Report), + undefined end. new_trusted_cert_entry(File, [CertsDb, RefDb, _ | _] = Db) -> -- cgit v1.2.3 From 911ab85688b21832c13d686d44c6b9064e9604a5 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Mon, 22 Aug 2016 09:57:57 -0400 Subject: Fixing CRL searching in cache bypass --- lib/ssl/src/ssl_crl.erl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/ssl/src/ssl_crl.erl b/lib/ssl/src/ssl_crl.erl index d9f21e04ac..01be1fb9ab 100644 --- a/lib/ssl/src/ssl_crl.erl +++ b/lib/ssl/src/ssl_crl.erl @@ -47,7 +47,7 @@ trusted_cert_and_path(CRL, issuer_not_found, {Db, DbRef} = DbHandle) -> {ok, unknown_crl_ca, []} end. -find_issuer(CRL, {Db,_}) -> +find_issuer(CRL, {Db,DbRef}) -> Issuer = public_key:pkix_normalize_name(public_key:pkix_crl_issuer(CRL)), IsIssuerFun = fun({_Key, {_Der,ErlCertCandidate}}, Acc) -> @@ -55,15 +55,27 @@ find_issuer(CRL, {Db,_}) -> (_, Acc) -> Acc end, - - try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, Db) of - issuer_not_found -> - {error, issuer_not_found} - catch - {ok, _} = Result -> - Result + if is_reference(DbRef) -> % actual DB exists + try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, Db) of + issuer_not_found -> + {error, issuer_not_found} + catch + {ok, _} = Result -> + Result + end; + is_tuple(DbRef), element(1,DbRef) =:= extracted -> % cache bypass byproduct + {extracted, CertsData} = DbRef, + Certs = [Entry || {decoded, Entry} <- CertsData], + try lists:foldl(IsIssuerFun, issuer_not_found, Certs) of + issuer_not_found -> + {error, issuer_not_found} + catch + {ok, _} = Result -> + Result + end end. + verify_crl_issuer(CRL, ErlCertCandidate, Issuer, NotIssuer) -> TBSCert = ErlCertCandidate#'OTPCertificate'.tbsCertificate, case public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.subject) of -- cgit v1.2.3 From dba6a3165e4cc8c2555c161510fd4caa82a1a96a Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Wed, 31 Aug 2016 18:40:58 -0400 Subject: Adding PEM cache bypass benchmark entries The benchmarks run through the local node only, as an attempt to show more potential contention on certificate usage. --- lib/ssl/test/ssl_bench_SUITE.erl | 102 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 7 deletions(-) diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl index ed439a425f..21989f8d99 100644 --- a/lib/ssl/test/ssl_bench_SUITE.erl +++ b/lib/ssl/test/ssl_bench_SUITE.erl @@ -25,11 +25,12 @@ suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. -all() -> [{group, setup}, {group, payload}]. +all() -> [{group, setup}, {group, payload}, {group, pem_cache}]. groups() -> [{setup, [{repeat, 3}], [setup_sequential, setup_concurrent]}, - {payload, [{repeat, 3}], [payload_simple]} + {payload, [{repeat, 3}], [payload_simple]}, + {pem_cache, [{repeat, 3}], [use_pem_cache, bypass_pem_cache]} ]. init_per_group(_GroupName, Config) -> @@ -49,9 +50,33 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ok. +init_per_testcase(use_pem_cache, Conf) -> + case bypass_pem_cache_supported() of + false -> {skipped, "PEM cache bypass support required"}; + true -> + application:set_env(ssl, bypass_pem_cache, false), + Conf + end; +init_per_testcase(bypass_pem_cache, Conf) -> + case bypass_pem_cache_supported() of + false -> {skipped, "PEM cache bypass support required"}; + true -> + application:set_env(ssl, bypass_pem_cache, true), + Conf + end; init_per_testcase(_Func, Conf) -> Conf. +end_per_testcase(use_pem_cache, _Config) -> + case bypass_pem_cache_supported() of + false -> ok; + true -> application:set_env(ssl, bypass_pem_cache, false) + end; +end_per_testcase(bypass_pem_cache, _Config) -> + case bypass_pem_cache_supported() of + false -> ok; + true -> application:set_env(ssl, bypass_pem_cache, false) + end; end_per_testcase(_Func, _Conf) -> ok. @@ -94,6 +119,18 @@ payload_simple(Config) -> {suite, "ssl"}, {name, "Payload simple"}]}), ok. +use_pem_cache(_Config) -> + {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()), + ct_event:notify(#event{name = benchmark_data, + data=[{value, Result}, + {suite, "ssl"}, {name, "Use PEM cache"}]}). + +bypass_pem_cache(_Config) -> + {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()), + ct_event:notify(#event{name = benchmark_data, + data=[{value, Result}, + {suite, "ssl"}, {name, "Bypass PEM cache"}]}). + ssl() -> test(ssl, ?COUNT, node()). @@ -172,6 +209,18 @@ server_init(ssl, payload, Loop, _, Server) -> ssl:close(TSocket) end, setup_server_connection(Socket, Test); +server_init(ssl, pem_cache, Loop, _, Server) -> + {ok, Socket} = ssl:listen(0, ssl_opts(listen_der)), + {ok, {_Host, Port}} = ssl:sockname(Socket), + {ok, Host} = inet:gethostname(), + Server ! {self(), {init, Host, Port}}, + Test = fun(TSocket) -> + ok = ssl:ssl_accept(TSocket), + Size = byte_size(msg()), + server_echo(TSocket, Size, Loop), + ssl:close(TSocket) + end, + setup_server_connection(Socket, Test); server_init(Type, Tc, _, _, Server) -> io:format("No server init code for ~p ~p~n",[Type, Tc]), @@ -185,6 +234,11 @@ client_init(Master, ssl, payload, Host, Port) -> Master ! {self(), init}, Size = byte_size(msg()), {Sock, Size}; +client_init(Master, ssl, pem_cache, Host, Port) -> + {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect_der)), + Master ! {self(), init}, + Size = byte_size(msg()), + {Sock, Size}; client_init(_Me, Type, Tc, Host, Port) -> io:format("No client init code for ~p ~p~n",[Type, Tc]), {Host, Port}. @@ -228,6 +282,13 @@ payload(Loop, ssl, D = {Socket, Size}) when Loop > 0 -> payload(_, _, {Socket, _}) -> ssl:close(Socket). +pem_cache(N, ssl, Data = {Socket, Size}) when N > 0 -> + ok = ssl:send(Socket, msg()), + {ok, _} = ssl:recv(Socket, Size), + pem_cache(N-1, ssl, Data); +pem_cache(_, _, {Socket, _}) -> + ssl:close(Socket). + msg() -> <<"Hello", 0:(512*8), @@ -352,16 +413,43 @@ stop_profile(fprof, File) -> ssl_opts(listen) -> [{backlog, 500} | ssl_opts("server")]; ssl_opts(connect) -> - [{verify, verify_peer} - | ssl_opts("client")]; + [{verify, verify_peer} | ssl_opts("client")]; +ssl_opts(listen_der) -> + [{backlog, 500} | ssl_opts("server_der")]; +ssl_opts(connect_der) -> + [{verify, verify_peer} | ssl_opts("client_der")]; ssl_opts(Role) -> - Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]), + CertData = cert_data(Role), [{active, false}, {depth, 2}, {reuseaddr, true}, {mode,binary}, {nodelay, true}, - {ciphers, [{dhe_rsa,aes_256_cbc,sha}]}, - {cacertfile, filename:join([Dir, Role, "cacerts.pem"])}, + {ciphers, [{dhe_rsa,aes_256_cbc,sha}]} + |CertData]. + +cert_data(Der) when Der =:= "server_der"; Der =:= "client_der" -> + [Role,_] = string:tokens(Der, "_"), + Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]), + {ok, CaCert0} = file:read_file(filename:join([Dir, Role, "cacerts.pem"])), + {ok, Cert0} = file:read_file(filename:join([Dir, Role, "cert.pem"])), + {ok, Key0} = file:read_file(filename:join([Dir, Role, "key.pem"])), + [{_, Cert, _}] = public_key:pem_decode(Cert0), + CaCert1 = public_key:pem_decode(CaCert0), + CaCert = [CCert || {_, CCert, _} <- CaCert1], + [{KeyType, Key, _}] = public_key:pem_decode(Key0), + [{cert, Cert}, + {cacerts, CaCert}, + {key, {KeyType, Key}}]; +cert_data(Role) -> + Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]), + [{cacertfile, filename:join([Dir, Role, "cacerts.pem"])}, {certfile, filename:join([Dir, Role, "cert.pem"])}, {keyfile, filename:join([Dir, Role, "key.pem"])}]. + +bypass_pem_cache_supported() -> + %% This function is currently critical to support cache bypass + %% and did not exist in prior versions. + catch ssl_pkix_db:module_info(), % ensure module is loaded + erlang:function_exported(ssl_pkix_db, extract_trusted_certs, 1). + -- cgit v1.2.3 From 71fb0e73995c3a0123a85b7cac42465bf083087c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 2 Sep 2016 16:11:36 +0200 Subject: ssl: Add new benchmarks to skip file for normal testing --- lib/ssl/test/ssl.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec index 86e14c033e..0ad94e22bc 100644 --- a/lib/ssl/test/ssl.spec +++ b/lib/ssl/test/ssl.spec @@ -1,4 +1,5 @@ {suites,"../ssl_test",all}. {skip_cases, "../ssl_test", - ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple], + ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple, + use_pem_cache, bypass_pem_cache], "Benchmarks run separately"}. -- cgit v1.2.3 From 3cad56eb508fb703d036e704bae77a3b3ae05086 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 12 Sep 2016 14:36:13 +0200 Subject: ssl: Add documentation of bypass_pem_cache application environment configuration --- lib/ssl/doc/src/ssl_app.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index a66e947bc1..f317dfded4 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -141,6 +141,16 @@ marker="ssl#clear_pem_cache-0">ssl:clear_pem_cache/0 + + ]]> + +

Introduced in ssl-8.0.2. Disables the PEM-cache. + The PEM cache has proven to be a bottleneck, until the + implementation has been improved this can be used as + a workaround. Defaults to false. +

+
+ ]]>

-- cgit v1.2.3