%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2008-2011. 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% %% %% -module(public_key_SUITE). %% Note: This directive should only be used in test suites. -compile(export_all). %%-include_lib("common_test/include/ct.hrl"). -include_lib("test_server/include/test_server.hrl"). -include_lib("public_key/include/public_key.hrl"). -define(TIMEOUT, 120000). % 2 min %% Test server callback functions %%-------------------------------------------------------------------- %% Function: init_per_suite(Config) -> Config %% Config - [tuple()] %% A list of key/value pairs, holding the test case configuration. %% Description: Initialization before the whole suite %% %% Note: This function is free to add any key/value pairs to the Config %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> try crypto:start() of ok -> Config catch _:_ -> {skip, "Crypto did not start"} end. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after the whole suite %%-------------------------------------------------------------------- end_per_suite(_Config) -> application:stop(crypto). %%-------------------------------------------------------------------- %% Function: init_per_testcase(TestCase, Config) -> Config %% Case - atom() %% Name of the test case that is about to be run. %% Config - [tuple()] %% A list of key/value pairs, holding the test case configuration. %% %% Description: Initialization before each test case %% %% Note: This function is free to add any key/value pairs to the Config %% variable, but should NOT alter/remove any existing entries. %% Description: Initialization before each test case %%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config0) -> Config = lists:keydelete(watchdog, 1, Config0), Dog = test_server:timetrap(?TIMEOUT), [{watchdog, Dog} | Config]. %%-------------------------------------------------------------------- %% Function: end_per_testcase(TestCase, Config) -> _ %% Case - atom() %% Name of the test case that is about to be run. %% Config - [tuple()] %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after each test case %%-------------------------------------------------------------------- end_per_testcase(_TestCase, Config) -> Dog = ?config(watchdog, Config), case Dog of undefined -> ok; _ -> test_server:timetrap_cancel(Dog) end. %%-------------------------------------------------------------------- %% Function: all(Clause) -> TestCases %% Clause - atom() - suite | doc %% TestCases - [Case] %% Case - atom() %% Name of a test case. %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [app, {group, pem_decode_encode}, {group, ssh_public_key_decode_encode}, encrypt_decrypt, {group, sign_verify}, pkix, pkix_path_validation]. groups() -> [{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem, dh_pem, cert_pem]}, {ssh_public_key_decode_encode, [], [ssh_rsa_public_key, ssh_dsa_public_key, ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment, ssh_rfc4716_rsa_subject, ssh_known_hosts, ssh_auth_keys, ssh1_known_hosts, ssh1_auth_keys, ssh_openssh_public_key_with_comment, ssh_openssh_public_key_long_header]}, {sign_verify, [], [rsa_sign_verify, dsa_sign_verify]} ]. init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. %% Test cases starts here. %%-------------------------------------------------------------------- app(doc) -> "Test that the public_key app file is ok"; app(suite) -> []; app(Config) when is_list(Config) -> ok = test_server:app_test(public_key). %%-------------------------------------------------------------------- dsa_pem(doc) -> [""]; dsa_pem(suite) -> []; dsa_pem(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), [{'DSAPrivateKey', DerDSAKey, not_encrypted} = Entry0 ] = erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")), DSAKey = public_key:der_decode('DSAPrivateKey', DerDSAKey), DSAKey = public_key:pem_entry_decode(Entry0), {ok, DSAPubPem} = file:read_file(filename:join(Datadir, "dsa_pub.pem")), [{'SubjectPublicKeyInfo', _, _} = PubEntry0] = public_key:pem_decode(DSAPubPem), DSAPubKey = public_key:pem_entry_decode(PubEntry0), true = check_entry_type(DSAPubKey, 'DSAPublicKey'), PubEntry0 = public_key:pem_entry_encode('SubjectPublicKeyInfo', DSAPubKey), DSAPubPemNoEndNewLines = strip_ending_newlines(DSAPubPem), DSAPubPemNoEndNewLines = strip_ending_newlines(public_key:pem_encode([PubEntry0])). %%-------------------------------------------------------------------- rsa_pem(doc) -> [""]; rsa_pem(suite) -> []; rsa_pem(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), [{'RSAPrivateKey', DerRSAKey, not_encrypted} = Entry0 ] = erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")), RSAKey0 = public_key:der_decode('RSAPrivateKey', DerRSAKey), RSAKey0 = public_key:pem_entry_decode(Entry0), [{'RSAPrivateKey', _, {_,_}} = Entry1] = erl_make_certs:pem_to_der(filename:join(Datadir, "rsa.pem")), true = check_entry_type(public_key:pem_entry_decode(Entry1, "abcd1234"), 'RSAPrivateKey'), {ok, RSAPubPem} = file:read_file(filename:join(Datadir, "rsa_pub.pem")), [{'SubjectPublicKeyInfo', _, _} = PubEntry0] = public_key:pem_decode(RSAPubPem), RSAPubKey = public_key:pem_entry_decode(PubEntry0), true = check_entry_type(RSAPubKey, 'RSAPublicKey'), PubEntry0 = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey), RSAPubPemNoEndNewLines = strip_ending_newlines(RSAPubPem), RSAPubPemNoEndNewLines = strip_ending_newlines(public_key:pem_encode([PubEntry0])), {ok, RSARawPem} = file:read_file(filename:join(Datadir, "rsa_pub_key.pem")), [{'RSAPublicKey', _, _} = PubEntry1] = public_key:pem_decode(RSARawPem), RSAPubKey = public_key:pem_entry_decode(PubEntry1), RSARawPemNoEndNewLines = strip_ending_newlines(RSARawPem), RSARawPemNoEndNewLines = strip_ending_newlines(public_key:pem_encode([PubEntry1])). %%-------------------------------------------------------------------- encrypted_pem(doc) -> [""]; encrypted_pem(suite) -> []; encrypted_pem(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), [{'RSAPrivateKey', DerRSAKey, not_encrypted}] = erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")), RSAKey = public_key:der_decode('RSAPrivateKey', DerRSAKey), Salt0 = crypto:rand_bytes(8), Entry0 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey, {{"DES-EDE3-CBC", Salt0}, "1234abcd"}), RSAKey = public_key:pem_entry_decode(Entry0,"1234abcd"), Des3KeyFile = filename:join(Datadir, "des3_client_key.pem"), erl_make_certs:der_to_pem(Des3KeyFile, [Entry0]), [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt0}}] = erl_make_certs:pem_to_der(Des3KeyFile), Salt1 = crypto:rand_bytes(8), Entry1 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey, {{"DES-CBC", Salt1}, "4567efgh"}), DesKeyFile = filename:join(Datadir, "des_client_key.pem"), erl_make_certs:der_to_pem(DesKeyFile, [Entry1]), [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} =Entry2] = erl_make_certs:pem_to_der(DesKeyFile), true = check_entry_type(public_key:pem_entry_decode(Entry2, "4567efgh"), 'RSAPrivateKey'). %%-------------------------------------------------------------------- dh_pem(doc) -> [""]; dh_pem(suite) -> []; dh_pem(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), [{'DHParameter', DerDH, not_encrypted} = Entry] = erl_make_certs:pem_to_der(filename:join(Datadir, "dh.pem")), erl_make_certs:der_to_pem(filename:join(Datadir, "new_dh.pem"), [Entry]), DHParameter = public_key:der_decode('DHParameter', DerDH), DHParameter = public_key:pem_entry_decode(Entry), Entry = public_key:pem_entry_encode('DHParameter', DHParameter). %%-------------------------------------------------------------------- cert_pem(doc) -> [""]; cert_pem(suite) -> []; cert_pem(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), [Entry0] = erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")), [{'Certificate', DerCert, not_encrypted} = Entry7] = erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")), Cert = public_key:der_decode('Certificate', DerCert), Cert = public_key:pem_entry_decode(Entry7), CertEntries = [{'Certificate', _, not_encrypted} = CertEntry0, {'Certificate', _, not_encrypted} = CertEntry1] = erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")), ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wcacerts.pem"), CertEntries), ok = erl_make_certs:der_to_pem(filename:join(Datadir, "wdsa.pem"), [Entry0]), NewCertEntries = erl_make_certs:pem_to_der(filename:join(Datadir, "wcacerts.pem")), true = lists:member(CertEntry0, NewCertEntries), true = lists:member(CertEntry1, NewCertEntries), [Entry0] = erl_make_certs:pem_to_der(filename:join(Datadir, "wdsa.pem")). %%-------------------------------------------------------------------- ssh_rsa_public_key(doc) -> ""; ssh_rsa_public_key(suite) -> []; ssh_rsa_public_key(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_rsa_pub")), [{PubKey, Attributes1}] = public_key:ssh_decode(RSARawSsh2, public_key), [{PubKey, Attributes1}] = public_key:ssh_decode(RSARawSsh2, rfc4716_public_key), {ok, RSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_rsa_pub")), [{PubKey, Attributes2}] = public_key:ssh_decode(RSARawOpenSsh, public_key), [{PubKey, Attributes2}] = public_key:ssh_decode(RSARawOpenSsh, openssh_public_key), %% Can not check EncodedSSh == RSARawSsh2 and EncodedOpenSsh %% = RSARawOpenSsh as line breakpoints may differ EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key), EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key), [{PubKey, Attributes1}] = public_key:ssh_decode(EncodedSSh, public_key), [{PubKey, Attributes2}] = public_key:ssh_decode(EncodedOpenSsh, public_key). %%-------------------------------------------------------------------- ssh_dsa_public_key(doc) -> ""; ssh_dsa_public_key(suite) -> []; ssh_dsa_public_key(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, DSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_dsa_pub")), [{PubKey, Attributes1}] = public_key:ssh_decode(DSARawSsh2, public_key), [{PubKey, Attributes1}] = public_key:ssh_decode(DSARawSsh2, rfc4716_public_key), {ok, DSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_dsa_pub")), [{PubKey, Attributes2}] = public_key:ssh_decode(DSARawOpenSsh, public_key), [{PubKey, Attributes2}] = public_key:ssh_decode(DSARawOpenSsh, openssh_public_key), %% Can not check EncodedSSh == DSARawSsh2 and EncodedOpenSsh %% = DSARawOpenSsh as line breakpoints may differ EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key), EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key), [{PubKey, Attributes1}] = public_key:ssh_decode(EncodedSSh, public_key), [{PubKey, Attributes2}] = public_key:ssh_decode(EncodedOpenSsh, public_key). %%-------------------------------------------------------------------- ssh_rfc4716_rsa_comment(doc) -> "Test comment header and rsa key"; ssh_rfc4716_rsa_comment(suite) -> []; ssh_rfc4716_rsa_comment(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_rsa_comment_pub")), [{#'RSAPublicKey'{} = PubKey, Attributes}] = public_key:ssh_decode(RSARawSsh2, public_key), Headers = proplists:get_value(headers, Attributes), Value = proplists:get_value("Comment", Headers, undefined), true = Value =/= undefined, RSARawSsh2 = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key). %%-------------------------------------------------------------------- ssh_rfc4716_dsa_comment(doc) -> "Test comment header and dsa key"; ssh_rfc4716_dsa_comment(suite) -> []; ssh_rfc4716_dsa_comment(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, DSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_dsa_comment_pub")), [{{_, #'Dss-Parms'{}} = PubKey, Attributes}] = public_key:ssh_decode(DSARawSsh2, public_key), Headers = proplists:get_value(headers, Attributes), Value = proplists:get_value("Comment", Headers, undefined), true = Value =/= undefined, %% Can not check Encoded == DSARawSsh2 as line continuation breakpoints may differ Encoded = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key), [{PubKey, Attributes}] = public_key:ssh_decode(Encoded, public_key). %%-------------------------------------------------------------------- ssh_rfc4716_rsa_subject(doc) -> "Test another header value than comment"; ssh_rfc4716_rsa_subject(suite) -> []; ssh_rfc4716_rsa_subject(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_subject_pub")), [{#'RSAPublicKey'{} = PubKey, Attributes}] = public_key:ssh_decode(RSARawSsh2, public_key), Headers = proplists:get_value(headers, Attributes), Value = proplists:get_value("Subject", Headers, undefined), true = Value =/= undefined, %% Can not check Encoded == RSARawSsh2 as line continuation breakpoints may differ Encoded = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key), [{PubKey, Attributes}] = public_key:ssh_decode(Encoded, public_key). %%-------------------------------------------------------------------- ssh_known_hosts(doc) -> ""; ssh_known_hosts(suite) -> []; ssh_known_hosts(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, SshKnownHosts} = file:read_file(filename:join(Datadir, "known_hosts")), [{#'RSAPublicKey'{}, Attributes1}, {#'RSAPublicKey'{}, Attributes2}] = Decoded = public_key:ssh_decode(SshKnownHosts, known_hosts), Value1 = proplists:get_value(hostnames, Attributes1, undefined), Value2 = proplists:get_value(hostnames, Attributes2, undefined), true = (Value1 =/= undefined) and (Value2 =/= undefined), Encoded = public_key:ssh_encode(Decoded, known_hosts), Decoded = public_key:ssh_decode(Encoded, known_hosts). %%-------------------------------------------------------------------- ssh1_known_hosts(doc) -> ""; ssh1_known_hosts(suite) -> []; ssh1_known_hosts(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, SshKnownHosts} = file:read_file(filename:join(Datadir, "ssh1_known_hosts")), [{#'RSAPublicKey'{}, Attributes1}, {#'RSAPublicKey'{}, Attributes2}] = Decoded = public_key:ssh_decode(SshKnownHosts, known_hosts), Value1 = proplists:get_value(hostnames, Attributes1, undefined), Value2 = proplists:get_value(hostnames, Attributes2, undefined), true = (Value1 =/= undefined) and (Value2 =/= undefined), Encoded = public_key:ssh_encode(Decoded, known_hosts), Decoded = public_key:ssh_decode(Encoded, known_hosts). %%-------------------------------------------------------------------- ssh_auth_keys(doc) -> ""; ssh_auth_keys(suite) -> []; ssh_auth_keys(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, SshAuthKeys} = file:read_file(filename:join(Datadir, "auth_keys")), [{#'RSAPublicKey'{}, Attributes1}, {{_, #'Dss-Parms'{}}, _Attributes2}] = Decoded = public_key:ssh_decode(SshAuthKeys, auth_keys), Value1 = proplists:get_value(options, Attributes1, undefined), true = Value1 =/= undefined, Encoded = public_key:ssh_encode(Decoded, auth_keys), Decoded = public_key:ssh_decode(Encoded, auth_keys). %%-------------------------------------------------------------------- ssh1_auth_keys(doc) -> ""; ssh1_auth_keys(suite) -> []; ssh1_auth_keys(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, SshAuthKeys} = file:read_file(filename:join(Datadir, "ssh1_auth_keys")), [{#'RSAPublicKey'{}, Attributes1}, {#'RSAPublicKey'{}, Attributes2}] = Decoded = public_key:ssh_decode(SshAuthKeys, auth_keys), Value1 = proplists:get_value(bits, Attributes1, undefined), Value2 = proplists:get_value(bits, Attributes2, undefined), true = (Value1 =/= undefined) and (Value2 =/= undefined), Encoded = public_key:ssh_encode(Decoded, auth_keys), Decoded = public_key:ssh_decode(Encoded, auth_keys). %%-------------------------------------------------------------------- ssh_openssh_public_key_with_comment(doc) -> "Test that emty lines and lines starting with # are ignored"; ssh_openssh_public_key_with_comment(suite) -> []; ssh_openssh_public_key_with_comment(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok, DSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_dsa_with_comment_pub")), [{{_, #'Dss-Parms'{}}, _}] = public_key:ssh_decode(DSARawOpenSsh, openssh_public_key). %%-------------------------------------------------------------------- ssh_openssh_public_key_long_header(doc) -> "Test that long headers are handled"; ssh_openssh_public_key_long_header(suite) -> []; ssh_openssh_public_key_long_header(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok,RSARawOpenSsh} = file:read_file(filename:join(Datadir, "ssh_rsa_long_header_pub")), [{#'RSAPublicKey'{}, _}] = Decoded = public_key:ssh_decode(RSARawOpenSsh, public_key), Encoded = public_key:ssh_encode(Decoded, rfc4716_public_key), Decoded = public_key:ssh_decode(Encoded, rfc4716_public_key). %%-------------------------------------------------------------------- encrypt_decrypt(doc) -> [""]; encrypt_decrypt(suite) -> []; encrypt_decrypt(Config) when is_list(Config) -> {PrivateKey, _DerKey} = erl_make_certs:gen_rsa(64), #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = PrivateKey, PublicKey = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")), RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey), Msg = public_key:decrypt_public(RsaEncrypted, PublicKey), Msg = public_key:decrypt_public(RsaEncrypted, PrivateKey), RsaEncrypted2 = public_key:encrypt_public(Msg, PublicKey), RsaEncrypted3 = public_key:encrypt_public(Msg, PrivateKey), Msg = public_key:decrypt_private(RsaEncrypted2, PrivateKey), Msg = public_key:decrypt_private(RsaEncrypted3, PrivateKey), ok. %%-------------------------------------------------------------------- rsa_sign_verify(doc) -> ["Checks that we can sign and verify rsa signatures."]; rsa_sign_verify(suite) -> []; rsa_sign_verify(Config) when is_list(Config) -> Ca = {_, CaKey} = erl_make_certs:make_cert([]), {Cert1, _} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]), PrivateRSA = #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} = public_key:pem_entry_decode(CaKey), PublicRSA = #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}, true = public_key:pkix_verify(Cert1, PublicRSA), Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")), RSASign = public_key:sign(Msg, sha, PrivateRSA), true = public_key:verify(Msg, sha, RSASign, PublicRSA), false = public_key:verify(<<1:8, Msg/binary>>, sha, RSASign, PublicRSA), false = public_key:verify(Msg, sha, <<1:8, RSASign/binary>>, PublicRSA), RSASign1 = public_key:sign(Msg, md5, PrivateRSA), true = public_key:verify(Msg, md5, RSASign1, PublicRSA). %%-------------------------------------------------------------------- dsa_sign_verify(doc) -> ["Checks that we can sign and verify dsa signatures."]; dsa_sign_verify(suite) -> []; dsa_sign_verify(Config) when is_list(Config) -> Ca = erl_make_certs:make_cert([]), CertInfo = {_,CertKey1} = erl_make_certs:make_cert([{key, dsa}, {issuer, Ca}]), {Cert2,_CertKey} = erl_make_certs:make_cert([{issuer, CertInfo}]), #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y, x=_X} = public_key:pem_entry_decode(CertKey1), true = public_key:pkix_verify(Cert2, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}), Datadir = ?config(data_dir, Config), [DsaKey = {'DSAPrivateKey', _, _}] = erl_make_certs:pem_to_der(filename:join(Datadir, "dsa.pem")), DSAPrivateKey = public_key:pem_entry_decode(DsaKey), #'DSAPrivateKey'{p=P1, q=Q1, g=G1, y=Y1, x=_X1} = DSAPrivateKey, Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")), DSASign = public_key:sign(Msg, sha, DSAPrivateKey), DSAPublicKey = Y1, DSAParams = #'Dss-Parms'{p=P1, q=Q1, g=G1}, true = public_key:verify(Msg, sha, DSASign, {DSAPublicKey, DSAParams}), false = public_key:verify(<<1:8, Msg/binary>>, sha, DSASign, {DSAPublicKey, DSAParams}), false = public_key:verify(Msg, sha, <<1:8, DSASign/binary>>, {DSAPublicKey, DSAParams}), Digest = crypto:sha(Msg), DigestSign = public_key:sign(Digest, none, DSAPrivateKey), true = public_key:verify(Digest, none, DigestSign, {DSAPublicKey, DSAParams}), <<_:8, RestDigest/binary>> = Digest, false = public_key:verify(<<1:8, RestDigest/binary>>, none, DigestSign, {DSAPublicKey, DSAParams}), false = public_key:verify(Digest, none, <<1:8, DigestSign/binary>>, {DSAPublicKey, DSAParams}). %%-------------------------------------------------------------------- pkix(doc) -> "Misc pkix tests not covered elsewhere"; pkix(suite) -> []; pkix(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), Certs0 = erl_make_certs:pem_to_der(filename:join(Datadir, "cacerts.pem")), Certs1 = erl_make_certs:pem_to_der(filename:join(Datadir, "client_cert.pem")), TestTransform = fun({'Certificate', CertDer, not_encrypted}) -> PlainCert = public_key:pkix_decode_cert(CertDer, plain), OtpCert = public_key:pkix_decode_cert(CertDer, otp), CertDer = public_key:pkix_encode('OTPCertificate', OtpCert, otp), CertDer = public_key:pkix_encode('Certificate', PlainCert, plain), OTPTBS = OtpCert#'OTPCertificate'.tbsCertificate, OTPSubj = OTPTBS#'OTPTBSCertificate'.subject, DNEncoded = public_key:pkix_encode('Name', OTPSubj, otp), PlainTBS = PlainCert#'Certificate'.tbsCertificate, Subj2 = PlainTBS#'TBSCertificate'.subject, DNEncoded = public_key:pkix_encode('Name', Subj2, plain), false = public_key:pkix_is_fixed_dh_cert(CertDer) end, [TestTransform(Cert) || Cert <- Certs0 ++ Certs1], true = public_key:pkix_is_self_signed(element(2,hd(Certs0))), false = public_key:pkix_is_self_signed(element(2,hd(Certs1))), CaIds = [element(2, public_key:pkix_issuer_id(Cert, self)) || {'Certificate', Cert, _} <- Certs0], {ok, IssuerId = {_, _IssuerName}} = public_key:pkix_issuer_id(element(2,hd(Certs1)), other), true = lists:member(IssuerId, CaIds), %% Should be normalized allready TestStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}], [{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]}, VerifyStr = {rdnSequence, [[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlang ca"}}], [{'AttributeTypeAndValue', {2,5,4,3},{printableString,"erlangca"}}]]}, VerifyStr = public_key:pkix_normalize_name(TestStr), ok. %%-------------------------------------------------------------------- pkix_path_validation(doc) -> "Misc pkix tests not covered elsewhere"; pkix_path_validation(suite) -> []; pkix_path_validation(Config) when is_list(Config) -> CaK = {Trusted,_} = erl_make_certs:make_cert([{key, dsa}, {subject, [ {name, "Public Key"}, {?'id-at-name', {printableString, "public_key"}}, {?'id-at-pseudonym', {printableString, "pubkey"}}, {city, "Stockholm"}, {country, "SE"}, {org, "erlang"}, {org_unit, "testing dep"} ]} ]), ok = erl_make_certs:write_pem("./", "public_key_cacert", CaK), CertK1 = {Cert1, _} = erl_make_certs:make_cert([{issuer, CaK}]), CertK2 = {Cert2,_} = erl_make_certs:make_cert([{issuer, CertK1}, {digest, md5}, {extensions, false}]), ok = erl_make_certs:write_pem("./", "public_key_cert", CertK2), {ok, _} = public_key:pkix_path_validation(Trusted, [Cert1], []), {error, {bad_cert,invalid_issuer}} = public_key:pkix_path_validation(Trusted, [Cert2], []), {ok, _} = public_key:pkix_path_validation(Trusted, [Cert1, Cert2], []), {error, issuer_not_found} = public_key:pkix_issuer_id(Cert2, other), CertK3 = {Cert3,_} = erl_make_certs:make_cert([{issuer, CertK1}, {extensions, [{basic_constraints, false}]}]), {Cert4,_} = erl_make_certs:make_cert([{issuer, CertK3}]), {error, {bad_cert,missing_basic_constraint}} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], []), VerifyFunAndState0 = {fun(_,{bad_cert, missing_basic_constraint}, UserState) -> {valid, UserState}; (_,{bad_cert, _} = Reason, _) -> {fail, Reason}; (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> {valid, UserState}; (_, valid_peer, UserState) -> {valid, UserState} end, []}, {ok, _} = public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4], [{verify_fun, VerifyFunAndState0}]), {error, {bad_cert, unknown_ca}} = public_key:pkix_path_validation(unknown_ca, [Cert1, Cert3, Cert4], []), VerifyFunAndState1 = {fun(_,{bad_cert, unknown_ca}, UserState) -> {valid, UserState}; (_,{bad_cert, _} = Reason, _) -> {fail, Reason}; (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> {valid, UserState} end, []}, {ok, _} = public_key:pkix_path_validation(unknown_ca, [Cert1], [{verify_fun, VerifyFunAndState1}]), ok. check_entry_type(#'DSAPrivateKey'{}, 'DSAPrivateKey') -> true; check_entry_type(#'RSAPrivateKey'{}, 'RSAPrivateKey') -> true; check_entry_type(#'RSAPublicKey'{}, 'RSAPublicKey') -> true; check_entry_type({_Int, #'Dss-Parms'{}}, 'DSAPublicKey') when is_integer(_Int) -> true; check_entry_type(#'DHParameter'{}, 'DHParameter') -> true; check_entry_type(#'Certificate'{}, 'Certificate') -> true; check_entry_type(_,_) -> false. strip_ending_newlines(Bin) -> string:strip(binary_to_list(Bin), right, 10).