1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2011-2013. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(pbe_SUITE).
   21: 
   22: -include_lib("common_test/include/ct.hrl").
   23: -include_lib("public_key/include/public_key.hrl").
   24: 
   25: %% Note: This directive should only be used in test suites.
   26: -compile(export_all).
   27: 
   28: %%--------------------------------------------------------------------
   29: %% Common Test interface functions -----------------------------------
   30: %%--------------------------------------------------------------------
   31: 
   32: suite() -> [{ct_hooks,[ts_install_cth]}].
   33: 
   34: all() -> 
   35:     [
   36:      pbdkdf1,
   37:      pbdkdf2,
   38:      encrypted_private_key_info].
   39: 
   40: groups() -> 
   41:     [].
   42: 
   43: %%--------------------------------------------------------------------
   44: init_per_suite(Config) ->
   45:     application:stop(crypto),
   46:     try crypto:start() of
   47: 	ok ->
   48: 	    Config
   49:     catch _:_ ->
   50: 	    {skip, "Crypto did not start"}
   51:     end.
   52: 
   53: end_per_suite(_Config) ->
   54:     application:stop(crypto).
   55: 
   56: %%--------------------------------------------------------------------
   57: 
   58: init_per_group(_GroupName, Config) ->
   59:     Config.
   60: 
   61: end_per_group(_GroupName, Config) ->
   62:     Config.
   63: 
   64: %%--------------------------------------------------------------------
   65: init_per_testcase(_TestCase, Config) ->
   66:    Config.
   67: 
   68: 
   69: end_per_testcase(_TestCase, _Config) ->
   70:    ok.
   71: 
   72: %%--------------------------------------------------------------------
   73: %% Test Cases --------------------------------------------------------
   74: %%--------------------------------------------------------------------
   75: 
   76: pbdkdf1() ->
   77:     [{doc,"Test with PKCS #5 PBKDF1 Test Vectors"}].
   78: pbdkdf1(Config) when is_list(Config) ->
   79:     %%Password = "password"
   80:     %%     = (0x)70617373776F7264
   81:     %%Salt     = (0x)78578E5A5D63CB06
   82:     %%Count    = 1000
   83:     %%kLen     = 16
   84:     %%Key      = PBKDF1(Password, Salt, Count, kLen)
   85:     %%= (0x)DC19847E05C64D2FAF10EBFB4A3D2A20
   86: 
   87:     Password = "password",
   88:     Salt = <<16#78,16#57,16#8E,16#5A,16#5D,16#63,16#CB,16#06>>,
   89:     Count = 1000,
   90: 
   91:    <<16#DC, 16#19, 16#84, 16#7E,
   92:      16#05, 16#C6, 16#4D, 16#2F,
   93:      16#AF, 16#10, 16#EB, 16#FB,
   94:      16#4A, 16#3D, 16#2A, 16#20, _/binary>> =
   95: 	pubkey_pbe:pbdkdf1(Password, Salt, Count, sha).
   96: 
   97: pbdkdf2() ->
   98:     [{doc,"Test with PKCS #5 PBKDF2 Test Vectors"}].
   99: pbdkdf2(Config) when is_list(Config) ->
  100:     %% Input:
  101:     %%   P = "password" (8 octets)
  102:     %%   S = "salt" (4 octets)
  103:     %%   c = 1
  104:     %%   dkLen = 20
  105:     
  106:     %% Output:
  107:     %%   DK = 0c 60 c8 0f 96 1f 0e 71
  108:     %%        f3 a9 b5 24 af 60 12 06
  109:     %%        2f e0 37 a6             (20 octets)
  110:     
  111:     <<16#0c, 16#60, 16#c8, 16#0f, 16#96, 16#1f, 16#0e, 16#71,
  112:       16#f3, 16#a9, 16#b5, 16#24, 16#af, 16#60, 16#12, 16#06,
  113:       16#2f, 16#e0, 16#37, 16#a6>> = pubkey_pbe:pbdkdf2("password", "salt", 1, 20, fun crypto:hmac/4, sha, 20),
  114:     
  115:     %% Input:
  116:     %%   P = "password" (8 octets)
  117:     %%   S = "salt" (4 octets)
  118:     %%   c = 2
  119:     %%   dkLen = 20
  120:     
  121:     %% Output:
  122:     %%   DK = ea 6c 01 4d c7 2d 6f 8c
  123:     %%   cd 1e d9 2a ce 1d 41 f0
  124:     %%   d8 de 89 57             (20 octets)
  125:     
  126:     <<16#ea, 16#6c, 16#01, 16#4d, 16#c7, 16#2d, 16#6f, 16#8c, 
  127:       16#cd, 16#1e, 16#d9, 16#2a, 16#ce, 16#1d, 16#41, 16#f0,  
  128:       16#d8,  16#de,  16#89, 16#57>>  =
  129: 	pubkey_pbe:pbdkdf2("password", "salt", 2, 20, fun crypto:hmac/4, sha, 20),
  130: 
  131:      %% Input:
  132:      %%   P = "password" (8 octets)
  133:      %%   S = "salt" (4 octets)
  134:      %%   c = 4096
  135:      %%   dkLen = 20
  136: 
  137:      %% Output:
  138:      %%   DK = 4b 00 79 01 b7 65 48 9a
  139:      %%        be ad 49 d9 26 f7 21 d0
  140:      %%        65 a4 29 c1             (20 octets)
  141: 
  142:     <<16#4b, 16#00, 16#79, 16#01, 16#b7, 16#65, 16#48, 16#9a,
  143:       16#be, 16#ad, 16#49, 16#d9, 16#26, 16#f7, 16#21, 16#d0,
  144:       16#65, 16#a4, 16#29, 16#c1>> = pubkey_pbe:pbdkdf2("password", "salt", 4096, 20, fun crypto:hmac/4, sha, 20),
  145: 
  146:     %% Input:
  147:     %%    P = "password" (8 octets)
  148:     %%    S = "salt" (4 octets)
  149:     %%    c = 16777216
  150:     %%    dkLen = 20
  151: 
  152:     %%  Output:
  153:     %%    DK = ee fe 3d 61 cd 4d a4 e4
  154:     %%         e9 94 5b 3d 6b a2 15 8c
  155:     %%         26 34 e9 84             (20 octets)
  156: 
  157:     
  158:     <<16#ee, 16#fe, 16#3d, 16#61, 16#cd, 16#4d, 16#a4, 16#e4, 
  159:       16#e9, 16#94, 16#5b, 16#3d, 16#6b, 16#a2, 16#15, 16#8c, 
  160:       16#26, 16#34, 16#e9, 16#84>> = pubkey_pbe:pbdkdf2("password", "salt", 16777216, 20, fun crypto:hmac/4, sha, 20),
  161:     
  162:     %% Input:
  163:     %%    P = "passwordPASSWORDpassword" (24 octets)
  164:     %%    S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets)
  165:     %%    c = 4096
  166:     %%    dkLen = 25
  167: 
  168:     %%  Output:
  169:     %%    DK = 3d 2e ec 4f e4 1c 84 9b
  170:     %%         80 c8 d8 36 62 c0 e4 4a
  171:     %%         8b 29 1a 96 4c f2 f0 70
  172:     %%         38                      (25 octets)
  173:     
  174:     <<16#3d, 16#2e, 16#ec, 16#4f, 16#e4, 16#1c, 16#84, 16#9b, 
  175:       16#80, 16#c8, 16#d8, 16#36, 16#62, 16#c0, 16#e4, 16#4a, 
  176:       16#8b, 16#29, 16#1a, 16#96, 16#4c, 16#f2, 16#f0, 16#70, 
  177:       16#38>>
  178: 	= pubkey_pbe:pbdkdf2("passwordPASSWORDpassword", 
  179: 			     "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25, fun crypto:hmac/4, sha, 20),
  180:     
  181:      %% Input:
  182:      %%   P = "pass\0word" (9 octets)
  183:      %%   S = "sa\0lt" (5 octets)
  184:      %%   c = 4096
  185:      %%   dkLen = 16
  186: 
  187:      %% Output:
  188:      %%   DK = 56 fa 6a a7 55 48 09 9d
  189:      %%        cc 37 d7 f0 34 25 e0 c3 (16 octets)
  190: 
  191:     <<16#56, 16#fa, 16#6a, 16#a7, 16#55, 16#48, 16#09, 16#9d, 
  192:       16#cc, 16#37, 16#d7, 16#f0, 16#34, 16#25, 16#e0, 16#c3>>
  193: 	= pubkey_pbe:pbdkdf2("pass\0word", 
  194: 			     "sa\0lt", 4096, 16, fun crypto:hmac/4, sha, 20).
  195:     
  196: encrypted_private_key_info() ->
  197:     [{doc,"Tests reading a EncryptedPrivateKeyInfo file encrypted with different ciphers"}].
  198: encrypted_private_key_info(Config) when is_list(Config) ->
  199:     Datadir = ?config(data_dir, Config),
  200:     {ok, PemDes} = file:read_file(filename:join(Datadir, "des_cbc_enc_key.pem")),
  201:     
  202:     PemDesEntry = public_key:pem_decode(PemDes),
  203:     ct:print("Pem entry: ~p" , [PemDesEntry]),
  204:     [{'PrivateKeyInfo', _, {"DES-CBC",_}} = PubEntry0] = PemDesEntry,
  205:     KeyInfo = public_key:pem_entry_decode(PubEntry0, "password"),
  206:     
  207:     {ok, Pem3Des} = file:read_file(filename:join(Datadir, "des_ede3_cbc_enc_key.pem")),
  208: 
  209:     Pem3DesEntry = public_key:pem_decode(Pem3Des),
  210:     ct:print("Pem entry: ~p" , [Pem3DesEntry]),
  211:     [{'PrivateKeyInfo', _, {"DES-EDE3-CBC",_}} = PubEntry1] = Pem3DesEntry,
  212:     KeyInfo = public_key:pem_entry_decode(PubEntry1, "password"),
  213: 
  214:     {ok, PemRc2} = file:read_file(filename:join(Datadir, "rc2_cbc_enc_key.pem")),
  215: 
  216:     PemRc2Entry = public_key:pem_decode(PemRc2),
  217:     ct:print("Pem entry: ~p" , [PemRc2Entry]),
  218:     [{'PrivateKeyInfo', _, {"RC2-CBC",_}} = PubEntry2] = PemRc2Entry,
  219:     KeyInfo = public_key:pem_entry_decode(PubEntry2, "password"),
  220: 
  221:     %% key generated with ssh-keygen -N hello_aes -f aes_128_cbc_enc_key
  222:     {ok, PemAesCbc} = file:read_file(filename:join(Datadir, "aes_128_cbc_enc_key")),
  223: 
  224:     PemAesCbcEntry = public_key:pem_decode(PemAesCbc),
  225:     ct:print("Pem entry: ~p" , [PemAesCbcEntry]),
  226:     [{'RSAPrivateKey', _, {"AES-128-CBC",_}} = PubAesCbcEntry] = PemAesCbcEntry,
  227:     #'RSAPrivateKey'{} = public_key:pem_entry_decode(PubAesCbcEntry, "hello_aes"),
  228: 
  229:     check_key_info(KeyInfo).
  230: 
  231: 
  232: check_key_info(#'PrivateKeyInfo'{privateKeyAlgorithm =
  233: 				     #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
  234: 				 privateKey = Key}) ->
  235:     #'RSAPrivateKey'{} = public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key)).