%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2008-2009. 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("test_server.hrl"). -include("test_server_line.hrl"). -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) -> crypto:start(), Config. %%-------------------------------------------------------------------- %% 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) -> crypto:stop(). %%-------------------------------------------------------------------- %% 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 %%-------------------------------------------------------------------- all(doc) -> ["Test the public_key rsa functionality"]; all(suite) -> [app, pem_to_der, decode_private_key %% encrypt_decrypt, %% rsa_verify %% dsa_verify_sign, %% pkix_encode_decode, %% pkix_verify_sign, %% pkix_path_validation ]. %% Test cases starts here. %%-------------------------------------------------------------------- app(doc) -> "Test that the public_key app file is ok"; app(suite) -> []; app(Config) when list(Config) -> ok = test_server:app_test(public_key). pem_to_der(doc) -> ["Check that supported PEM files are decoded into the expected entry type"]; pem_to_der(suite) -> []; pem_to_der(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok,[{dsa_private_key, _, not_encrypted}]} = public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), {ok,[{rsa_private_key, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "client_key.pem")), {ok,[{rsa_private_key, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "rsa.pem")), {ok,[{rsa_private_key, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"), {ok, Bin0} = file:read_file(filename:join(Datadir, "rsa.pem")), {ok, [{rsa_private_key, _, _}]} = public_key:pem_to_der(Bin0, "abcd1234"), {ok,[{dh_params, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "dh.pem")), {ok,[{cert, _, not_encrypted}]} = public_key:pem_to_der(filename:join(Datadir, "client_cert.pem")), {ok,[{cert_req, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "req.pem")), {ok,[{cert, _, _}, {cert, _, _}]} = public_key:pem_to_der(filename:join(Datadir, "cacerts.pem")), {ok, Bin1} = file:read_file(filename:join(Datadir, "cacerts.pem")), {ok, [{cert, _, _}, {cert, _, _}]} = public_key:pem_to_der(Bin1), ok. %%-------------------------------------------------------------------- decode_private_key(doc) -> ["Check that private keys are decode to the expected key type."]; decode_private_key(suite) -> []; decode_private_key(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok,[DsaKey = {dsa_private_key, _DsaKey, _}]} = public_key:pem_to_der(filename:join(Datadir, "dsa.pem")), {ok,[RsaKey = {rsa_private_key, _RsaKey,_}]} = public_key:pem_to_der(filename:join(Datadir, "client_key.pem")), {ok,[ProtectedRsaKey1 = {rsa_private_key, _ProtectedRsaKey1,_}]} = public_key:pem_to_der(filename:join(Datadir, "rsa.pem"), "abcd1234"), {ok,[ProtectedRsaKey2 = {rsa_private_key, _ProtectedRsaKey2,_}]} = public_key:pem_to_der(filename:join(Datadir, "rsa.pem")), {ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey), {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(RsaKey), {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey1), {ok, #'RSAPrivateKey'{}} = public_key:decode_private_key(ProtectedRsaKey2, "abcd1234"), ok. %%-------------------------------------------------------------------- encrypt_decrypt(doc) -> [""]; encrypt_decrypt(suite) -> []; encrypt_decrypt(Config) when is_list(Config) -> RSAPrivateKey = #'RSAPrivateKey'{publicExponent = 17, modulus = 3233, privateExponent = 2753, prime1 = 61, prime2 = 53, version = 'two-prime'}, Msg = <<0,123>>, {ok, Encrypted} = public_key:encrypt(Msg, RSAPrivateKey, [{block_type, 2}]), test_server:format("Expected 855, Encrypted ~p ~n", [Encrypted]), ok. %% Datadir = ?config(data_dir, Config), %% {ok,[{rsa_private_key, EncKey}]} = %% public_key:pem_to_der(filename:join(Datadir, "server_key.pem")), %% {ok, Key} = public_key:decode_private_key(EncKey, rsa), %% RSAPublicKey = #'RSAPublicKey'{publicExponent = %% Key#'RSAPrivateKey'.publicExponent, %% modulus = Key#'RSAPrivateKey'.modulus}, %% {ok, Msg} = file:read_file(filename:join(Datadir, "msg.txt")), %% Hash = crypto:sha(Msg), %% {ok, Encrypted} = public_key:encrypt(Hash, Key, [{block_type, 2}]), %% test_server:format("Encrypted ~p", [Encrypted]), %% {ok, Decrypted} = public_key:decrypt(Encrypted, %% RSAPublicKey, [{block_type, 1}]), %% test_server:format("Encrypted ~p", [Decrypted]), %% true = Encrypted == Decrypted. %%-------------------------------------------------------------------- rsa_verify(doc) -> ["Cheks that we can verify an rsa signature."]; rsa_verify(suite) -> []; rsa_verify(Config) when is_list(Config) -> Datadir = ?config(data_dir, Config), {ok,[{cert, DerCert}]} = public_key:pem_to_der(filename:join(Datadir, "server_cert.pem")), {ok, OTPCert} = public_key:pkix_decode_cert(DerCert, otp), {0, Signature} = OTPCert#'Certificate'.signature, TBSCert = OTPCert#'Certificate'.tbsCertificate, #'TBSCertificate'{subjectPublicKeyInfo = Info} = TBSCert, #'SubjectPublicKeyInfo'{subjectPublicKey = RSAPublicKey} = Info, EncTBSCert = encoded_tbs_cert(DerCert), Digest = crypto:sha(EncTBSCert), public_key:verify_signature(Digest, Signature, RSAPublicKey). %% Signature is generated in the following way (in datadir): %% openssl dgst -sha1 -binary -out rsa_signature -sign server_key.pem msg.txt %%{ok, Signature} = file:read_file(filename:join(Datadir, "rsa_signature")), %%{ok, Signature} = file:read_file(filename:join(Datadir, "rsa_signature")), %% {ok, Msg} = file:read_file(filename:join(Datadir, "msg.txt")), %% Digest = crypto:sha(Msg), %% {ok,[{rsa_private_key, EncKey}]} = %% public_key:pem_to_der(filename:join(Datadir, "server_key.pem")), %% {ok, Key} = public_key:decode_private_key(EncKey, rsa), %% RSAPublicKey = #'RSAPublicKey'{publicExponent = %% Key#'RSAPrivateKey'.publicExponent, %% modulus = Key#'RSAPrivateKey'.modulus}, encoded_tbs_cert(Cert) -> {ok, PKIXCert} = 'OTP-PUB-KEY':decode_TBSCert_exclusive(Cert), {'Certificate', {'Certificate_tbsCertificate', EncodedTBSCert}, _, _} = PKIXCert, EncodedTBSCert.