aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key
diff options
context:
space:
mode:
Diffstat (limited to 'lib/public_key')
-rw-r--r--lib/public_key/doc/src/public_key.xml13
-rw-r--r--lib/public_key/src/pubkey_pbe.erl30
-rw-r--r--lib/public_key/src/pubkey_pem.erl4
-rw-r--r--lib/public_key/src/public_key.erl39
-rw-r--r--lib/public_key/test/pbe_SUITE.erl38
-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.pem30
7 files changed, 110 insertions, 44 deletions
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 806f7c5b0f..e6bcedd1b1 100644
--- a/lib/public_key/src/pubkey_pbe.erl
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -42,15 +42,14 @@
encode(Data, Password, "DES-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:block_encrypt(des_cbc, Key, IV, pbe_pad(Data, KeyDevParams));
-
encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
<<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
crypto:block_encrypt(des3_cbc, [Key1, Key2, Key3], IV, pbe_pad(Data));
-
encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:block_encrypt(rc2_cbc, Key, IV, pbe_pad(Data, KeyDevParams)).
+
%%--------------------------------------------------------------------
-spec decode(binary(), string(), string(), term()) -> binary().
%%
@@ -59,21 +58,20 @@ encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
decode(Data, Password,"DES-CBC"= Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:block_decrypt(des_cbc, Key, IV, Data);
-
decode(Data, Password,"DES-EDE3-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
<<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
crypto:block_decrypt(des3_cbc, [Key1, Key2, Key3], IV, Data);
-
decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, 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);
+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).
-decode(Data, Password,"AES-128-CBC"= Cipher, IV) ->
- %% PKCS5_SALT_LEN is 8 bytes
- <<Salt:8/binary,_/binary>> = IV,
- {Key, _} = password_to_key_and_iv(Password, Cipher, Salt),
- crypto:block_decrypt(aes_cbc128, Key, IV, Data).
%%--------------------------------------------------------------------
-spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary().
@@ -131,13 +129,15 @@ password_to_key_and_iv(Password, _Cipher, {#'PBEParameter'{salt = Salt,
<<Key:8/binary, IV:8/binary, _/binary>>
= pbdkdf1(Password, Salt, Count, Hash),
{Key, IV};
-password_to_key_and_iv(Password, Cipher, Salt) ->
- KeyLen = derived_key_length(Cipher, undefined),
+password_to_key_and_iv(Password, Cipher, KeyDevParams) ->
+ %% PKCS5_SALT_LEN is 8 bytes
+ <<Salt:8/binary,_/binary>> = KeyDevParams,
+ KeyLen = derived_key_length(Cipher, undefined),
<<Key:KeyLen/binary, _/binary>> =
pem_encrypt(<<>>, Password, Salt, ceiling(KeyLen div 16), <<>>, md5),
%% Old PEM encryption does not use standard encryption method
- %% pbdkdf1 and uses then salt as IV
- {Key, Salt}.
+ %% pbdkdf1
+ {Key, KeyDevParams}.
pem_encrypt(_, _, _, 0, Acc, _) ->
Acc;
pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
@@ -267,7 +267,9 @@ derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or
(Cipher == "DES-EDE3-CBC") ->
24;
derived_key_length(Cipher,_) when (Cipher == "AES-128-CBC") ->
- 16.
+ 16;
+derived_key_length(Cipher,_) when (Cipher == "AES-256-CBC") ->
+ 32.
cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
"DES-CBC";
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 523c9e2515..1136267411 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,23 +197,11 @@ 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) ->
@@ -225,13 +213,33 @@ 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)),
PemEntry = public_key:pem_decode(PemKey),
- ct:print("Pem entry: ~p" , [PemEntry]),
+ ct:pal("Pem entry: ~p" , [PemEntry]),
[{Asn1Type, _, {Cipher,_} = CipherInfo} = PubEntry] = PemEntry,
#'RSAPrivateKey'{} = KeyInfo = public_key:pem_entry_decode(PubEntry, Password),
PemKey1 = public_key:pem_encode([public_key:pem_entry_encode(Asn1Type, KeyInfo, {CipherInfo, Password})]),
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-----