diff options
Diffstat (limited to 'lib/public_key')
-rw-r--r-- | lib/public_key/asn1/OTP-PKIX.asn1 | 8 | ||||
-rw-r--r-- | lib/public_key/doc/src/notes.xml | 52 | ||||
-rw-r--r-- | lib/public_key/doc/src/public_key.xml | 13 | ||||
-rw-r--r-- | lib/public_key/src/pubkey_pbe.erl | 18 | ||||
-rw-r--r-- | lib/public_key/src/pubkey_pem.erl | 4 | ||||
-rw-r--r-- | lib/public_key/src/public_key.erl | 39 | ||||
-rw-r--r-- | lib/public_key/test/pbe_SUITE.erl | 37 | ||||
-rw-r--r-- | lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc.pem (renamed from lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc_enc_key.pem) | 0 | ||||
-rw-r--r-- | lib/public_key/test/pbe_SUITE_data/old_aes_256_cbc.pem | 30 | ||||
-rw-r--r-- | lib/public_key/vsn.mk | 2 |
10 files changed, 165 insertions, 38 deletions
diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1 index 9bcd99fba3..ff3250b383 100644 --- a/lib/public_key/asn1/OTP-PKIX.asn1 +++ b/lib/public_key/asn1/OTP-PKIX.asn1 @@ -233,9 +233,13 @@ countryName ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= { -- regarding how to handle and sometimes accept incorrect certificates -- we define and use the type below instead of X520countryName + -- We accept utf8String encoding of the US-ASCII + -- country name code and the mix up with other country code systems + -- that uses three characters instead of two. + OTP-X520countryname ::= CHOICE { - printableString PrintableString (SIZE (2)), - utf8String UTF8String (SIZE (2)) + printableString PrintableString (SIZE (2..3)), + utf8String UTF8String (SIZE (2..3)) } serialNumber ATTRIBUTE-TYPE-AND-VALUE-CLASS ::= { diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index d83dd24f41..d13c9a520a 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,58 @@ <file>notes.xml</file> </header> +<section><title>Public_Key 1.6.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + RSA options passed to crypto for encrypt and decrypt with + public or private key.</p> + <p> + Own Id: OTP-15754 Aux Id: ERL-878 </p> + </item> + <item> + <p> + Fix dialyzer warnings caused by a faulty type + specification for digest_type().</p> + <p> + This change updates digest_type() and the functions + operating with this argument type to accept both 'sha1' + and 'sha' as digest_type().</p> + <p> + Own Id: OTP-15776</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add possibility to read PEM files encrypted with old PEM + encryption using AES-256</p> + <p> + Own Id: OTP-13726</p> + </item> + <item> + <p> + Relax decoding of certificates to so that "harmless" + third party encoding errors may be accepted but not + created by the public_key application. This adds + acceptance of using an incorrect three character country + code, the PKIX standard use two character country codes. + It is also accepted that the country code is utf8 encoded + but the specification says it should be ASCII.</p> + <p> + Own Id: OTP-15687 Aux Id: PR-2162 </p> + </item> + </list> + </section> + +</section> + <section><title>Public_Key 1.6.6</title> <section><title>Improvements and New Features</title> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index b7589f6653..12bb0b21b0 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -286,7 +286,9 @@ entries as ASN.1 DER encoded entities.</fsummary> <desc> <p>Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.</p> - <p>Example <c>{ok, PemBin} = file:read_file("cert.pem").</c></p> + <p>Example <c>{ok, PemBin} = file:read_file("cert.pem"). + PemEntries = public_key:pem_decode(PemBin). + </c></p> </desc> </func> @@ -423,7 +425,7 @@ <p>Available options:</p> <taglist> - <tag>{verify_fun, fun()}</tag> + <tag>{verify_fun, {fun(), InitialUserState::term()}</tag> <item> <p>The fun must be defined as:</p> @@ -541,7 +543,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, <tag>{undetermined_details, boolean()}</tag> <item> - <p>Defaults to false. When revocation status can not be + <p>Defaults to false. When revocation status cannot be determined, and this option is set to true, details of why no CRLs where accepted are included in the return value.</p> </item> @@ -736,7 +738,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, <note><p> Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain - and they can not be used to achieve real security. This function is provided for testing purposes only. + and they cannot be used to achieve real security. This function is provided for testing purposes only. </p></note> </desc> </func> @@ -813,7 +815,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, <p>The <c>{OtherRefId,term()}</c> is defined by the user and is passed to the <c>match_fun</c>, if defined. If the term in <c>OtherRefId</c> is a binary, it will be converted to a string. </p> - <p>The <c>ip</c> Reference ID takes an <seealso marker="inet:inet#type-ip_address">inet:ip_address()</seealso> + <p>The <c>ip</c> Reference ID takes an + <seealso marker="kernel:inet#type-ip_address">inet:ip_address()</seealso> or an ip address in string format (E.g "10.0.1.1" or "1234::5678:9012") as second element. </p> <p>The options are:</p> diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl index b9fe219dcf..6003bf21d0 100644 --- a/lib/public_key/src/pubkey_pbe.erl +++ b/lib/public_key/src/pubkey_pbe.erl @@ -49,10 +49,13 @@ encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) -> crypto:block_encrypt(rc2_cbc, Key, IV, pbe_pad(Data, block_size(rc2_cbc))); encode(Data, Password, "AES-128-CBC" = Cipher, KeyDevParams) -> {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), - crypto:block_encrypt(aes_cbc128, Key, IV, pbe_pad(Data, block_size(aes_128_cbc))); + crypto:block_encrypt(aes_128_cbc, Key, IV, pbe_pad(Data, block_size(aes_128_cbc))); +encode(Data, Password, "AES-192-CBC" = Cipher, KeyDevParams) -> + {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), + crypto:block_encrypt(aes_192_cbc, Key, IV, pbe_pad(Data, block_size(aes_192_cbc))); encode(Data, Password, "AES-256-CBC"= Cipher, KeyDevParams) -> {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), - crypto:block_encrypt(aes_cbc256, Key, IV, pbe_pad(Data, block_size(aes_256_cbc))). + crypto:block_encrypt(aes_256_cbc, Key, IV, pbe_pad(Data, block_size(aes_256_cbc))). %%-------------------------------------------------------------------- -spec decode(binary(), string(), string(), term()) -> binary(). @@ -71,13 +74,16 @@ decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) -> crypto:block_decrypt(rc2_cbc, Key, IV, Data); decode(Data, Password,"AES-128-CBC"= Cipher, KeyDevParams) -> {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), - crypto:block_decrypt(aes_cbc128, Key, IV, Data); + crypto:block_decrypt(aes_128_cbc, Key, IV, Data); +decode(Data, Password,"AES-192-CBC"= Cipher, KeyDevParams) -> + {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), + crypto:block_decrypt(aes_192_cbc, Key, IV, Data); decode(Data, Password,"AES-256-CBC"= Cipher, KeyDevParams) -> {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams), - crypto:block_decrypt(aes_cbc256, Key, IV, Data). + crypto:block_decrypt(aes_256_cbc, Key, IV, Data). %%-------------------------------------------------------------------- --spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary(). +-spec pbdkdf1(iodata(), iodata(), integer(), atom()) -> binary(). %% %% Description: Implements password based decryption key derive function 1. %% Exported mainly for testing purposes. @@ -89,7 +95,7 @@ pbdkdf1(Password, Salt, Count, Hash) -> do_pbdkdf1(Result, Count-1, Result, Hash). %%-------------------------------------------------------------------- --spec pbdkdf2(string(), iodata(), integer(), integer(), fun(), atom(), integer()) +-spec pbdkdf2(iodata(), iodata(), integer(), integer(), fun(), atom(), integer()) -> binary(). %% %% Description: Implements password based decryption key derive function 2. diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl index d7e5bc3ad8..0fd1453f7c 100644 --- a/lib/public_key/src/pubkey_pem.erl +++ b/lib/public_key/src/pubkey_pem.erl @@ -101,10 +101,10 @@ encode_pem_entry({'PrivateKeyInfo', Der, EncParams}) -> EncDer = encode_encrypted_private_keyinfo(Der, EncParams), StartStr = pem_start('EncryptedPrivateKeyInfo'), [StartStr, "\n", b64encode_and_split(EncDer), "\n", pem_end(StartStr) ,"\n\n"]; -encode_pem_entry({Type, Der, {Cipher, Salt}}) -> +encode_pem_entry({Type, Decrypted, {Cipher, Salt}}) -> StartStr = pem_start(Type), [StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n\n", - b64encode_and_split(Der), "\n", pem_end(StartStr) ,"\n\n"]. + b64encode_and_split(Decrypted), "\n", pem_end(StartStr) ,"\n\n"]. decode_pem_entries([], Entries) -> lists:reverse(Entries); diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index d02df27a00..47266c514c 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -407,8 +407,7 @@ decrypt_private(CipherText, Options) when is_binary(CipherText), is_list(Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), Padding). + crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), default_options(Options)). %%-------------------------------------------------------------------- %% Description: Public key decryption using the public key. @@ -429,8 +428,7 @@ decrypt_public(CipherText, Key) -> PlainText :: binary() . decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, Options) when is_binary(CipherText), is_list(Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - crypto:public_decrypt(rsa, CipherText,[E, N], Padding). + crypto:public_decrypt(rsa, CipherText,[E, N], default_options(Options)). %%-------------------------------------------------------------------- %% Description: Public key encryption using the public key. @@ -452,8 +450,7 @@ encrypt_public(PlainText, Key) -> CipherText :: binary() . encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, Options) when is_binary(PlainText), is_list(Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - crypto:public_encrypt(rsa, PlainText, [E,N], Padding). + crypto:public_encrypt(rsa, PlainText, [E,N], default_options(Options)). %%-------------------------------------------------------------------- %% @@ -481,8 +478,7 @@ encrypt_private(PlainText, when is_binary(PlainText), is_integer(N), is_integer(E), is_integer(D), is_list(Options) -> - Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding), - crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding). + crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), default_options(Options)). %%-------------------------------------------------------------------- %% Description: List available group sizes among the pre-computed dh groups @@ -1235,6 +1231,33 @@ pkix_test_root_cert(Name, Opts) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +default_options([]) -> + [{rsa_padding, rsa_pkcs1_padding}]; +default_options(Opts) -> + case proplists:get_value(rsa_pad, Opts) of + undefined -> + case proplists:get_value(rsa_padding, Opts) of + undefined -> + case lists:dropwhile(fun erlang:is_tuple/1, Opts) of + [Pad|_] -> + set_padding(Pad, Opts); + [] -> + set_padding(rsa_pkcs1_padding, Opts) + end; + Pad -> + set_padding(Pad, Opts) + end; + Pad -> + set_padding(Pad, Opts) + end. + +set_padding(Pad, Opts) -> + [{rsa_padding,Pad} | [{T,V} || {T,V} <- Opts, + T =/= rsa_padding, + T =/= rsa_pad] + ]. + + format_sign_key(Key = #'RSAPrivateKey'{}) -> {rsa, format_rsa_private_key(Key)}; format_sign_key(#'DSAPrivateKey'{p = P, q = Q, g = G, x = X}) -> diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl index 5dea35dce6..61db282dfa 100644 --- a/lib/public_key/test/pbe_SUITE.erl +++ b/lib/public_key/test/pbe_SUITE.erl @@ -37,7 +37,7 @@ all() -> [ pbdkdf1, pbdkdf2, - old_enc, + old_pbe, pbes1, pbes2]. @@ -197,29 +197,18 @@ pbdkdf2(Config) when is_list(Config) -> = pubkey_pbe:pbdkdf2("pass\0word", "sa\0lt", 4096, 16, fun crypto:hmac/4, sha, 20). -old_enc() -> - [{doc,"Tests encode/decode RSA key encrypted with different ciphers using old PEM encryption scheme"}]. -old_enc(Config) when is_list(Config) -> - Datadir = proplists:get_value(data_dir, Config), - %% key generated with ssh-keygen -N hello_aes -f old_aes_128_cbc_enc_key.pem - {ok, PemAesCbc} = file:read_file(filename:join(Datadir, "old_aes_128_cbc_enc_key.pem")), - - PemAesCbcEntry = public_key:pem_decode(PemAesCbc), - ct:print("Pem entry: ~p" , [PemAesCbcEntry]), - [{'RSAPrivateKey', _, {"AES-128-CBC",_}} = PubAesCbcEntry] = PemAesCbcEntry, - #'RSAPrivateKey'{} = public_key:pem_entry_decode(PubAesCbcEntry, "hello_aes"). - pbes1() -> [{doc,"Tests encode/decode EncryptedPrivateKeyInfo encrypted with different ciphers using PBES1"}]. pbes1(Config) when is_list(Config) -> decode_encode_key_file("pbes1_des_cbc_md5_enc_key.pem", "password", "DES-CBC", Config). - + pbes2() -> [{doc,"Tests encode/decode EncryptedPrivateKeyInfo encrypted with different ciphers using PBES2"}]. pbes2(Config) when is_list(Config) -> decode_encode_key_file("pbes2_des_cbc_enc_key.pem", "password", "DES-CBC", Config), decode_encode_key_file("pbes2_des_ede3_cbc_enc_key.pem", "password", "DES-EDE3-CBC", Config), decode_encode_key_file("pbes2_aes_128_enc_key.pem", "password", "AES-128-CBC", Config), + decode_encode_key_file("pbes2_aes_192_enc_key.pem", "password", "AES-192-CBC", Config), decode_encode_key_file("pbes2_aes_256_enc_key.pem", "password", "AES-256-CBC", Config), case lists:member(rc2_cbc, proplists:get_value(ciphers, crypto:supports())) of true -> @@ -227,7 +216,27 @@ pbes2(Config) when is_list(Config) -> false -> ok end. +old_pbe() -> + [{doc,"Tests encode/decode with old format used before PBE"}]. +old_pbe(Config) when is_list(Config) -> + Datadir = proplists:get_value(data_dir, Config), + % key generated with ssh-keygen -N hello_aes -f old_aes_128_cbc.pem + {ok, PemAes128Cbc} = file:read_file(filename:join(Datadir, "old_aes_128_cbc.pem")), + + PemAes128CbcEntries = public_key:pem_decode(PemAes128Cbc), + ct:print("Pem entry: ~p" , [PemAes128CbcEntries]), + [{'RSAPrivateKey', _, {"AES-128-CBC",_}} = Aes128CbcEntry] = PemAes128CbcEntries, + #'RSAPrivateKey'{} = Key = public_key:pem_entry_decode(Aes128CbcEntry, "hello_aes"), + + %% Converted with openssl rsa -in old_aes_128_cbc.pem -out old_aes_256_cbc.pem -aes256 + {ok, PemAes256Cbc} = file:read_file(filename:join(Datadir, "old_aes_256_cbc.pem")), + + PemAes256CbcEntries = public_key:pem_decode(PemAes256Cbc), + ct:print("Pem entry: ~p" , [PemAes256CbcEntries]), + [{'RSAPrivateKey', _, {"AES-256-CBC",_}} = Aes256CbcEntry] = PemAes256CbcEntries, + Key = public_key:pem_entry_decode(Aes256CbcEntry, "hello_aes"). + decode_encode_key_file(File, Password, Cipher, Config) -> Datadir = proplists:get_value(data_dir, Config), {ok, PemKey} = file:read_file(filename:join(Datadir, File)), diff --git a/lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc_enc_key.pem b/lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc.pem index 34c7543f30..34c7543f30 100644 --- a/lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc_enc_key.pem +++ b/lib/public_key/test/pbe_SUITE_data/old_aes_128_cbc.pem diff --git a/lib/public_key/test/pbe_SUITE_data/old_aes_256_cbc.pem b/lib/public_key/test/pbe_SUITE_data/old_aes_256_cbc.pem new file mode 100644 index 0000000000..e6aec2869d --- /dev/null +++ b/lib/public_key/test/pbe_SUITE_data/old_aes_256_cbc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,ABDA22398E511E9465983E1A50706044 + +XhIcPOb6pTWL++pgeeTH5rsx0tackhllVqyXyOfbYMBJnVFRhQ/V/1MDg3Jt4wD1 +Nerhcv5srHeiwmf+vwXwDFOzvFzLVM1jFMUJe/2XloYFX4TBiLZAF/zekQA3uPY6 +DKJuBuO5vVSZ0VlxGpu3jphIAwxbssfZkZmryCP3b1/oX5Y3Em/wEWW3RduaeWFu +Z2nTsPH3yNmHkuqFF3cq0aZs+VxtjcuYo0gbkN5hNVgOoOVxIBzw7DsgBAkdXvr3 +LRCMGg7Y2pVthA963s0xkN37XtZEiYbydoLnzHlW/Kx5QSvED8/Fn94Lcdy5NsQN +7nYWWgYZRH39Wnsi0BrTZv399U5rBe7DnpStKWPn2Sa8Bdu3CX2oLajM1cZjAp1X +y6vuasK7SoZ8rWpcsHQpV1HyNBTl/uRU5nrYc/KGD8l2x7tdNidGx2Hey/6O4H5v +rxL1TB4PlzDYwCsReuyLbEjyuZQ10j0SK/SFzikHuvD2IEpM/oUaPdVFqcW8/sjw +VhcsupAf4EXfsi2dJBylmDjI2W7h9XwBDLzQN+69DtkBmvimE5CguTITf8MAHQQ6 +Q1vYF2ij7W675tj9ulksRPaMxSsI03luai/Jrieh0mPqGEenGEEC5QU0XPOvsfyw +GMYaBUbdYrMpbHM3wFPxM2wRlXf4gX5BhZKRGZX7OaEs54pfglyQtTPuZmD0VcAp +EWHq70G9mbuBlhbMX1rKAomuDmIvgLeLRUpAFf59Qr8KoJSLD1S8TJB3uEPk6i39 +4GnylbpmqS4gv/OIc6WTeOeUZTAD3A77HBwSlELPk3/s1d/MLyfciYClOBEuZ6NB +FXEKCGCEC786zJA678gLEaa2XPNkEM+2gjzNFqtYMIn5ehAq/HRRsFvW+wkTbee4 +z+qe5HbVKAQ3EOfbidvYrDaGd7HvHVG8zosl+O61iIFs04lLEMDFXBIdvIgEncOK +Rq3yXdpBKMg89aoZLniaPobSvuvdjNOMzW6EKlb5FKZduCiR68MEZ+rLHYHTwE3W +Z5+TCbrbV2F6WQpq3zqnB14wGu8igEb5Veq+N2vMkx4iTMTUyCty1SwIjj4NidM1 +dJM7Ighdal6tQ6hIwbDfpIPsY4eGH/UrdVZ0SkxuDR2s76cZ8nFX3lJ/BNwTZLKo +IqAC4NjUOv3ID+0Q6Lz+sxLCi5pLYUf0E+s4pgi1BYAOu+BF3GwxyqnqVoq/Fs5D +LXxuY0946YM+WcrYzke4mq3MPx6QQYj04H5KJ2mzxtnbZJrfLF23PVRVhvgKSjyV +I3/zgJ16fV2H/fb26oCpTNbb11pQvhorkLwdvpwtM+go7dJGebAi1762Nbj/CqnW +fbBPxPRvNPZn6pEodJ/L/APhvGv1K7eC9THj66H7Kmeoq8Lz74idhywP9I3QS0ZO +15ORbTDjuiRYNJPxxu79A3/tWMUlprJ9ljhI/0DXRB0M3UGic52D/32Q64I7eewy +qRNS/3C3ejDShIRBDFTdDkM3s/42LySXJjmjU9bpZY4POQ3kOaJb3EzSvbzTyXzu +3FiHvDQY+b8XwbxtE/kTMaAPQZ7TtWOao7SRi7J94MvCQ5/tbakFP2suM8psnigC +-----END RSA PRIVATE KEY----- diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index c68806d856..a5e4ec8d5a 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.6.6 +PUBLIC_KEY_VSN = 1.6.7 |