aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2011-10-18 18:01:40 +0200
committerIngela Anderton Andin <[email protected]>2011-11-01 16:54:26 +0100
commitb211df3a0cca478822d57836dac3dd6452aab32a (patch)
treef825012c084fd9bc88b4ed6fb0c04d079a3ca747
parentca4d1197fdf66fda5241edd645c12d2451b67ec8 (diff)
downloadotp-b211df3a0cca478822d57836dac3dd6452aab32a.tar.gz
otp-b211df3a0cca478822d57836dac3dd6452aab32a.tar.bz2
otp-b211df3a0cca478822d57836dac3dd6452aab32a.zip
Additions to crypto and public_key needed for full PKCS-8 support
-rw-r--r--lib/crypto/c_src/crypto.c27
-rw-r--r--lib/crypto/doc/src/crypto.xml30
-rw-r--r--lib/crypto/src/crypto.erl34
-rw-r--r--lib/crypto/test/crypto_SUITE.erl22
-rw-r--r--lib/public_key/src/pubkey_pbe.erl105
-rw-r--r--lib/public_key/src/public_key.erl1
-rw-r--r--lib/public_key/test/pbe_SUITE.erl60
7 files changed, 182 insertions, 97 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 10fe333d18..802c1991de 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -154,7 +154,7 @@ static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -234,7 +234,7 @@ static ErlNifFunc nif_funcs[] = {
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_40_cbc_crypt", 4, rc2_40_cbc_crypt},
+ {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
@@ -1237,30 +1237,31 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
return enif_make_tuple2(env,new_state,new_data);
}
-static ERL_NIF_TERM rc2_40_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,IVec,Data,IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
RC2_KEY rc2_key;
ERL_NIF_TERM ret;
-
+ unsigned char iv_copy[8];
+
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || key_bin.size != 5
+ || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
|| !enif_inspect_binary(env, argv[1], &ivec_bin)
|| ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
-
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 8 != 0) {
return enif_make_badarg(env);
}
-
- RC2_set_key(&rc2_key, 5, key_bin.data, 40);
+
+ RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
+ memcpy(iv_copy, ivec_bin.data, 8);
RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
+ enif_make_new_binary(env, data_bin.size, &ret),
data_bin.size, &rc2_key,
- ivec_bin.data,
+ iv_copy,
(argv[3] == atom_true));
-
return ret;
-}
+}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type,Data,Key=[E,N,D]) */
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 824be09438..48243fd693 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="latin1" ?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -334,14 +334,16 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
<name>sha_mac(Key, Data) -> Mac</name>
+ <name>sha_mac(Key, Data, MacLength) -> Mac</name>
<fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
<type>
<v>Key = Data = iolist() | binary()</v>
<v>Mac = binary()</v>
+ <v>MacLenength = integer() =&lt; 20 </v>
</type>
<desc>
<p>Computes an <c>SHA MAC</c> message authentification code
- from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ from <c>Key</c> and <c>Data</c>, where the default length of the Mac
is 160 bits (20 bytes).</p>
</desc>
</func>
@@ -1046,6 +1048,30 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
</func>
<func>
+ <name>rc2_cbc_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rc2_cbc_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypts <c>Cipher</c>according to RC2 in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>Ivec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to RC2 in CBC mode.</p>
+ </desc>
+ </func>
+
+ <func>
<name>rc4_encrypt(Key, Data) -> Result</name>
<fsummary>Encrypt data using RC4</fsummary>
<type>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index e3b921f9fa..0714cb686d 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -27,7 +27,7 @@
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
%-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
%-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
--export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]).
+-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
-export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
@@ -42,7 +42,7 @@
-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
--export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
+-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]).
-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
@@ -83,7 +83,7 @@
dss_verify,dss_sign,
rsa_verify,rsa_sign,
rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
dh_generate_key, dh_compute_key,
aes_cbc_128_encrypt, aes_cbc_128_decrypt,
exor,
@@ -91,7 +91,7 @@
rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
%% idea_cbc_encrypt, idea_cbc_decrypt,
aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- aes_ctr_encrypt, aes_ctr_decrypt,
+ aes_ctr_encrypt, aes_ctr_decrypt,
aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
info_lib]).
@@ -260,6 +260,9 @@ md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
sha_mac(Key, Data) ->
sha_mac_n(Key,Data,20).
+sha_mac(Key, Data, Size) ->
+ sha_mac_n(Key, Data, Size).
+
sha_mac_96(Key, Data) ->
sha_mac_n(Key,Data,12).
@@ -689,16 +692,25 @@ rc4_encrypt(_Key, _Data) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+
+%% RC2 block cipher
+
+rc2_cbc_encrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
+
+rc2_cbc_decrypt(Key, IVec, Data) ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
+
+rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
%%
-%% RC2 - 40 bits block cipher
+%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
-rc2_40_cbc_encrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,true).
-
-rc2_40_cbc_decrypt(Key, IVec, Data) ->
- rc2_40_cbc_crypt(Key,IVec,Data,false).
+rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,true).
-rc2_40_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
+ rc2_cbc_crypt(Key,IVec,Data,false).
%%
%% DH Diffie-Hellman functions
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 53b4c2a7e1..86acdc27df 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -49,6 +49,7 @@
des_ecb/1,
des3_cbc/1,
des3_cfb/1,
+ rc2_cbc/1,
aes_cfb/1,
aes_cbc/1,
aes_cbc_iter/1,
@@ -79,8 +80,10 @@ all() ->
md5_mac_io, sha, sha_update,
hmac_update_sha, hmac_update_sha_n, hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
%% sha256, sha256_update, sha512,sha512_update,
- des_cbc, des_cfb, des3_cbc, des3_cfb, aes_cfb, aes_cbc,
+ des_cbc, des_cfb, des3_cbc, des3_cfb, rc2_cbc, aes_cfb, aes_cbc,
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_cfb_iter, des_ecb,
+ des_cbc, rc2_cbc, aes_cfb, aes_cbc,
+ aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
dsa_sign_test, rsa_encrypt_decrypt, dh, exor_test,
@@ -347,7 +350,7 @@ hmac_update_md5(Config) when is_list(Config) ->
Key2 = "A fine speach by a fine man!",
?line Long1 = "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the proposition that all men are created equal.",
?line Long2 = "Now we are engaged in a great civil war, testing whether that nation, or any nation, so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.",
- ?line Long3 = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us-that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion—that we here highly resolve that these dead shall not have died in vain-that this nation, under God, shall have a new birth of freedom-and that government of the people, by the people, for the people, shall not perish from the earth.",
+ ?line Long3 = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us-that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion that we here highly resolve that these dead shall not have died in vain-that this nation, under God, shall have a new birth of freedom-and that government of the people, by the people, for the people, shall not perish from the earth.",
?line CtxA = crypto:hmac_init(md5, Key2),
?line CtxB = crypto:hmac_update(CtxA, Long1),
?line CtxC = crypto:hmac_update(CtxB, Long2),
@@ -604,6 +607,21 @@ des_ecb(Config) when is_list(Config) ->
?line m(Cipher5, <<"he time ">>),
?line Cipher6 = crypto:des_ecb_decrypt(Key, hexstr2bin("893d51ec4b563b53")),
?line m(Cipher6, <<"for all ">>).
+%%
+%%
+rc2_cbc(doc) ->
+ "Encrypt and decrypt according to RC2 CBC and check the result. "
+ "Example stripped out from public_key application test";
+rc2_cbc(Config) when is_list(Config) ->
+
+ Key = <<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>,
+ IV = <<72,91,135,182,25,42,35,210>>,
+
+ Cipher = <<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>>,
+ Text = <<48,130,1,85,2,1,0,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,4,130,1,63,48,130, 1,59,2,1,0,2,65,0,222,187,252,44,9,214,27,173,162,169,70,47,36,34,78,84,204, 107,60,192,117,95,21,206,49,142,245,126,121,223,23,2,107,106,133,204,161,36, 40,2,114,69,4,93,242,5,42,50,154,47,154,211,209,123,120,161,5,114,173,155,34, 191,52,59,2,3,1,0,1,2,64,45,144,169,106,220,236,71,39,67,82,123,192,35,21,61, 143,13,110,150,180,12,142,210,40,39,109,70,125,132,51,6,66,159,134,112,85, 155,243,118,221,65,133,127,99,151,194,252,141,149,224,229,62,214,45,228,32, 184,85,67,14,228,161,184,161,2,33,0,255,202,240,131,130,57,49,224,115,255,83, 79,6,165,212,21,179,212,20,188,97,74,69,68,163,223,247,237,39,24,23,235,2,33, 0,222,234,48,36,33,23,219,45,59,136,55,245,143,29,165,48,255,131,207,146,131, 104,13,163,54,131,236,78,88,54,16,241,2,33,0,230,2,99,129,173,176,166,131, 241,106,143,76,9,107,70,41,121,185,228,39,124,200,159,62,216,169,5,180,111, 169,255,159,2,33,0,151,193,70,212,209,210,179,219,175,83,165,4,255,81,103,76, 92,39,24,0,222,132,208,3,244,241,10,198,171,54,227,129,2,32,43,250,20,31,16, 189,168,116,225,1,125,132,94,130,118,124,28,56,232,39,69,218,244,33,240,200, 205,9,215,101,35,135,7,7,7,7,7,7,7>>,
+
+ Text = crypto:rc2_cbc_decrypt(Key, IV, Cipher),
+ Cipher = crypto:rc2_cbc_encrypt(Key, IV, Text).
%%
%%
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
index f471871d35..32be347039 100644
--- a/lib/public_key/src/pubkey_pbe.erl
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -27,35 +27,43 @@
-define(DEFAULT_SHA_MAC_KEYLEN, 20).
--define(OCTET_STR, 4).
--define(IV_LEN, 8).
+-define(ASN1_OCTET_STR_TAG, 4).
+-define(IV_LEN, 8).
%%====================================================================
%% Internal application API
%%====================================================================
-pbdkdf2(Password, Salt, Count, DerivedKeyLen, PrfLen, Prf)->
- NumBlocks = ceiling(DerivedKeyLen / PrfLen),
- NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfLen ,
- blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt, Count, Prf, PrfLen, <<>>).
+pbdkdf2(Password, Salt, Count, DerivedKeyLen, Prf, PrfOutputLen)->
+ NumBlocks = ceiling(DerivedKeyLen / PrfOutputLen),
+ NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfOutputLen ,
+ blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt, Count, Prf, PrfOutputLen, <<>>).
encode(Data, Password, "DES-CBC" = Cipher, KeyDevParams) ->
- {Key, IV} = password_to_key_and_iv(Password, derived_key_length(Cipher), KeyDevParams),
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:des_cbc_encrypt(Key, IV, Data);
encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
- {Key, IV} = password_to_key_and_iv(Password, derived_key_length(Cipher), KeyDevParams),
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
<<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data).
+ crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data);
+
+encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_encrypt(Key, IV, Data).
decode(Data, Password,"DES-CBC"= Cipher, KeyDevParams) ->
- {Key, IV} = password_to_key_and_iv(Password, derived_key_length(Cipher), KeyDevParams),
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:des_cbc_decrypt(Key, IV, Data);
decode(Data, Password,"DES-EDE3-CBC" = Cipher, KeyDevParams) ->
- {Key, IV} = password_to_key_and_iv(Password, derived_key_length(Cipher), KeyDevParams),
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
<<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
- crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data).
+ crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data);
+
+decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_decrypt(Key, IV, Data).
%%--------------------------------------------------------------------
-spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary().
@@ -94,13 +102,20 @@ decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-password_to_key_and_iv(Password, KeyLen, {salt, Salt}) ->
+password_to_key_and_iv(Password, Cipher, {salt, Salt}) ->
+ 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}.
+password_to_key_and_iv(Password, _, #'PBES2-params'{} = Params) ->
+ {Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen, IV} =
+ key_derivation_params(Params),
+ <<Key:KeyLen/binary, _/binary>> =
+ pbdkdf2(Password, Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen),
+ {Key, IV}.
pem_encrypt(_, _, _, 0, Acc, _) ->
Acc;
pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
@@ -118,8 +133,12 @@ iv(#'PBES2-params_encryptionScheme'{algorithm = Algo,
(Algo == ?'des-EDE3-CBC') ->
%% This is an so called open ASN1-type that in this
%% case will be an octet-string of length 8
- <<?OCTET_STR, ?IV_LEN, IV:?IV_LEN/binary>> = ASNIV,
- IV.
+ <<?ASN1_OCTET_STR_TAG, ?IV_LEN, IV:?IV_LEN/binary>> = ASNIV,
+ IV;
+iv(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC',
+ parameters = ASN1IV}) ->
+ {ok, #'RC2-CBC-Parameter'{iv = IV}} = 'PKCS-FRAME':decode('RC2-CBC-Parameter', ASN1IV),
+ iolist_to_binary(IV).
blocks(1, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
<<XorSum:N/binary, _/binary>> = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
@@ -129,53 +148,55 @@ blocks(NumBlocks, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf, PrfLen, <<Acc/binary, XorSum/binary>>).
xor_sum(Password, Salt, Count, Index, Prf, PrfLen) ->
- %%Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
- Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>]),
+ Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
do_xor_sum(Prf, PrfLen, Result, Password, Count-1, Result).
do_xor_sum(_, _, _, _, 0, Acc) ->
Acc;
do_xor_sum(Prf, PrfLen, Prev, Password, Count, Acc)->
- %%Result = Prf(Password, Prev, PrfLen),
- Result = Prf(Password, Prev),
+ Result = Prf(Password, Prev, PrfLen),
do_xor_sum(Prf, PrfLen, Result, Password, Count-1, crypto:exor(Acc, Result)).
decrypt_parameters(?'id-PBES2', DekParams) ->
{ok, Params} = 'PKCS-FRAME':decode('PBES2-params', DekParams),
{cipher(Params#'PBES2-params'.encryptionScheme), Params}.
-key_derivation_params(#'PBES2-params_keyDerivationFunc'{algorithm = ?'id-PBKDF2',
- parameters =
- #'PBKDF2-params'{salt = {specified, OctetSalt},
- iterationCount = Count,
- keyLength = Length,
- prf = Prf}}) ->
- PseudoRandomFunction = pseudo_random_function(Prf),
- KeyLen = pseudo_key_length(Length, Prf),
- {iolist_to_binary(OctetSalt), Count, KeyLen, PseudoRandomFunction}.
-
+key_derivation_params(#'PBES2-params'{keyDerivationFunc = KeyDerivationFunc,
+ encryptionScheme = EncScheme}) ->
+ #'PBES2-params_keyDerivationFunc'{algorithm = ?'id-PBKDF2',
+ parameters =
+ #'PBKDF2-params'{salt = {specified, OctetSalt},
+ iterationCount = Count,
+ keyLength = Length,
+ prf = Prf}} = KeyDerivationFunc,
+ #'PBES2-params_encryptionScheme'{algorithm = Algo} = EncScheme,
+ {PseudoRandomFunction, PseudoOtputLen} = pseudo_random_function(Prf),
+ KeyLen = derived_key_length(Algo, Length),
+ {iolist_to_binary(OctetSalt), Count, KeyLen, PseudoRandomFunction, PseudoOtputLen, iv(EncScheme)}.
+
+%% This function currently matches a tuple that ougth to be the value ?'id-hmacWithSHA1,
+%% but we need some kind of ASN1-fix for this.
pseudo_random_function(#'PBKDF2-params_prf'{algorithm = {_,_, _,'id-hmacWithSHA1'}}) ->
- %%fun crypto:sha_mac_n/3.
- fun crypto:sha_mac/2.
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')}.
-pseudo_key_length(asn1_NOVALUE, #'PBKDF2-params_prf'{algorithm = {_,_, _,'id-hmacWithSHA1'}}) ->
- ?DEFAULT_SHA_MAC_KEYLEN;
-pseudo_key_length(Len, _) when is_integer(Len) ->
- Len.
+pseudo_output_length(?'id-hmacWithSHA1') ->
+ ?DEFAULT_SHA_MAC_KEYLEN.
-derived_key_length("DES-CBC") ->
+derived_key_length(_, Len) when is_integer(Len) ->
+ Len;
+derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or (Cipher == "DES-CBC") ->
8;
-%% derived_key_length("RC2-CBC") ->
-%% 5;
-derived_key_length("DES-EDE3-CBC") ->
+derived_key_length(Cipher,_) when (Cipher == ?'rc2CBC') or (Cipher == "RC2-CBC") ->
+ 16;
+derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or (Cipher == "DES-EDE3-CBC") ->
24.
cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
"DES-CBC";
cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'des-EDE3-CBC'}) ->
- "DES-EDE3-CBC".
-%% cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC'}) ->
-%% "RC2-CBC".
+ "DES-EDE3-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC'}) ->
+ "RC2-CBC".
ceiling(Float) ->
erlang:round(Float + 0.5).
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 68c7b7ad93..19465e7828 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -154,7 +154,6 @@ der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or (Asn1Type == '
andalso is_binary(Der) ->
try
{ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
-
Decoded
catch
error:{badmatch, {error, _}} = Error ->
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
index 1d33976505..8dc9a01529 100644
--- a/lib/public_key/test/pbe_SUITE.erl
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -20,6 +20,7 @@
-module(pbe_SUITE).
-include_lib("test_server/include/test_server.hrl").
+-include_lib("public_key/include/public_key.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -157,7 +158,7 @@ pbdkdf2(Config) when is_list(Config) ->
<<16#ea, 16#6c, 16#01, 16#4d, 16#c7, 16#2d, 16#6f, 16#8c,
16#cd, 16#1e, 16#d9, 16#2a, 16#ce, 16#1d, 16#41, 16#f0,
16#d8, 16#de, 16#89, 16#57>> =
- pubkey_pbe:pbdkdf2("password", "salt", 2, 20, 20, fun crypto:sha_mac/2),
+ pubkey_pbe:pbdkdf2("password", "salt", 2, 20, fun crypto:sha_mac/3, 20),
%% Input:
%% P = "password" (8 octets)
@@ -172,7 +173,7 @@ pbdkdf2(Config) when is_list(Config) ->
<<16#4b, 16#00, 16#79, 16#01, 16#b7, 16#65, 16#48, 16#9a,
16#be, 16#ad, 16#49, 16#d9, 16#26, 16#f7, 16#21, 16#d0,
- 16#65, 16#a4, 16#29, 16#c1>> = pubkey_pbe:pbdkdf2("password", "salt", 4096, 20, 20, fun crypto:sha_mac/2),
+ 16#65, 16#a4, 16#29, 16#c1>> = pubkey_pbe:pbdkdf2("password", "salt", 4096, 20, fun crypto:sha_mac/3, 20),
%% Input:
%% P = "password" (8 octets)
@@ -188,7 +189,7 @@ pbdkdf2(Config) when is_list(Config) ->
<<16#ee, 16#fe, 16#3d, 16#61, 16#cd, 16#4d, 16#a4, 16#e4,
16#e9, 16#94, 16#5b, 16#3d, 16#6b, 16#a2, 16#15, 16#8c,
- 16#26, 16#34, 16#e9, 16#84>> = pubkey_pbe:pbdkdf2("password", "salt", 16777216, 20, 20, fun crypto:sha_mac/2),
+ 16#26, 16#34, 16#e9, 16#84>> = pubkey_pbe:pbdkdf2("password", "salt", 16777216, 20, fun crypto:sha_mac/3, 20),
%% Input:
%% P = "passwordPASSWORDpassword" (24 octets)
@@ -207,7 +208,7 @@ pbdkdf2(Config) when is_list(Config) ->
16#8b, 16#29, 16#1a, 16#96, 16#4c, 16#f2, 16#f0, 16#70,
16#38>>
= pubkey_pbe:pbdkdf2("passwordPASSWORDpassword",
- "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, 20, fun crypto:sha_mac/2),
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, fun crypto:sha_mac/3, 20),
%% Input:
%% P = "pass\0word" (9 octets)
@@ -222,30 +223,37 @@ pbdkdf2(Config) when is_list(Config) ->
<<16#56, 16#fa, 16#6a, 16#a7, 16#55, 16#48, 16#09, 16#9d,
16#cc, 16#37, 16#d7, 16#f0, 16#34, 16#25, 16#e0, 16#c3>>
= pubkey_pbe:pbdkdf2("pass\0word",
- "sa\0lt", 4096, 16, 20, fun crypto:sha_mac/2).
+ "sa\0lt", 4096, 16, fun crypto:sha_mac/3, 20).
-
-pbe_des_cbc(doc) ->
- ["Tests reading a password DES-CBC encrypted key file"];
-pbe_des_cbc(Config) when is_list(Config) ->
+encrypted_private_key_info(doc) ->
+ ["Tests reading a EncryptedPrivateKeyInfo file different ciphers"];
+encrypted_private_key_info(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
- {ok, Pem} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
+ {ok, PemDes} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
+ PemDesEntry = public_key:pem_decode(PemDes),
+ test_server:format("Pem entry: ~p" , [PemDesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-CBC",_}} = PubEntry0] = PemDesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry0, "password"),
- PemE = public_key:pem_decode(Pem),
- test_server:format("PemE: ~p" , [PemE]),
- [{'PrivateKeyInfo', _, _} = PubEntry0] = PemE,
- Key = public_key:pem_entry_decode(PubEntry0, "password"),
- test_server:format("Key: ~p" , [Key]).
-
-pbe_des3_ede(doc) ->
- ["Tests reading a password DES-CBC encrypted key file"];
-pbe_des3_ede(Config) when is_list(Config) ->
- Datadir = ?config(data_dir, Config),
- {ok, Pem} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
+ {ok, Pem3Des} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
+
+ Pem3DesEntry = public_key:pem_decode(Pem3Des),
+ test_server:format("Pem entry: ~p" , [Pem3DesEntry]),
+ [{'PrivateKeyInfo', _, {"DES-EDE3-CBC",_}} = PubEntry1] = Pem3DesEntry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry1, "password"),
+
+ {ok, PemRc2} = file:read_file(filename:join(Datadir, "rc2_cbc_enc_key.pem")),
+
+ PemRc2Entry = public_key:pem_decode(PemRc2),
+ test_server:format("Pem entry: ~p" , [PemRc2Entry]),
+ [{'PrivateKeyInfo', _, {"RC2-CBC",_}} = PubEntry2] = PemRc2Entry,
+ KeyInfo = public_key:pem_entry_decode(PubEntry2, "password"),
+
+ check_key_info(KeyInfo).
+
- PemE = public_key:pem_decode(Pem),
- test_server:format("PemE: ~p" , [PemE]),
- [{'PrivateKeyInfo', _, _} = PubEntry0] = PemE,
- Key = public_key:pem_entry_decode(PubEntry0, "password"),
- test_server:format("Key: ~p" , [Key]).
+check_key_info(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
+ privateKey = Key}) ->
+ #'RSAPrivateKey'{} = public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key)).