1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(crypto_SUITE). 22 23-include_lib("common_test/include/ct.hrl"). 24 25-export([all/0, suite/0, 26 t_md5/1,t_md5_update/1,error/1,unaligned_context/1,random_lists/1, 27 misc_errors/1]). 28 29suite() -> 30 [{ct_hooks,[ts_install_cth]}]. 31 32all() -> 33 [t_md5, t_md5_update, error, unaligned_context, 34 random_lists, misc_errors]. 35 36%% Test crc32, adler32 and md5 error cases not covered by other tests" 37misc_errors(Config) when is_list(Config) -> 38 ct:timetrap({minutes, 2}), 39 1 = erlang:adler32([]), 40 L = lists:duplicate(600,3), 41 1135871753 = erlang:adler32(L), 42 L2 = lists:duplicate(22000,3), 43 1100939744 = erlang:adler32(L2), 44 {'EXIT', {badarg,_}} = (catch erlang:adler32(L++[a])), 45 {'EXIT', {badarg,_}} = (catch erlang:crc32(L++[a])), 46 {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|<<25:7>>])), 47 {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|4])), 48 Big = 111111111111111111111111111111, 49 {'EXIT', {badarg,_}} = (catch erlang:crc32(Big,<<"hej">>)), 50 {'EXIT', {badarg,_}} = (catch erlang:crc32(25,[1,2,3|4])), 51 {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(Big,3,3)), 52 {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,Big,3)), 53 {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,3,Big)), 54 {'EXIT', {badarg,_}} = (catch erlang:adler32(Big,<<"hej">>)), 55 {'EXIT', {badarg,_}} = (catch erlang:adler32(25,[1,2,3|4])), 56 {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(Big,3,3)), 57 {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,Big,3)), 58 {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,3,Big)), 59 {'EXIT', {badarg,_}} = (catch erlang:md5_update(<<"hej">>,<<"hej">>)), 60 {'EXIT', {badarg,_}} = (catch erlang:md5_final(<<"hej">>)), 61 ok. 62 63 64%% 65%% Most of the real code for these test cases are in 66%% the modules crypto_reference and random_iolist. 67%% 68-define(REF,crypto_reference). 69 70nicesplit(N,L) -> 71 nicesplit(N,L,[]). 72nicesplit(0,Tail,Acc) -> 73 {lists:reverse(Acc),Tail}; 74nicesplit(_,[],Acc) -> 75 {lists:reverse(Acc),[]}; 76nicesplit(N,[H|Tail],Acc) -> 77 nicesplit(N-1,Tail,[H|Acc]). 78 79run_in_para([],_) -> 80 true; 81run_in_para(FunList,Schedulers) -> 82 {ThisTime,NextTime} = nicesplit(Schedulers,FunList), 83 case length(ThisTime) of 84 1 -> 85 [{L,Fun}] = ThisTime, 86 try 87 Fun() 88 catch 89 _:Reason -> 90 exit({error_at_line,L,Reason}) 91 end; 92 _ -> 93 These = [ {L,erlang:spawn_monitor(F)} || {L,F} <- ThisTime ], 94 collect_workers(These) 95 end, 96 run_in_para(NextTime,Schedulers). 97 98collect_workers([]) -> 99 ok; 100collect_workers([{L,{Pid,Ref}}|T]) -> 101 receive 102 {'DOWN',Ref,process,Pid,normal} -> 103 collect_workers(T); 104 {'DOWN',Ref,process,Pid,Other} -> 105 exit({error_at_line,L,Other}) 106 end. 107 108%% Test crc32, adler32 and md5 on a number of pseudo-randomly generated lists. 109random_lists(Config) when is_list(Config) -> 110 ct:timetrap({minutes, 5}), 111 Num = erlang:system_info(schedulers_online), 112 B = list_to_binary( 113 lists:duplicate( 114 (erlang:system_info(context_reductions)*10) - 50,$!)), 115 CRC32_1 = fun(L) -> erlang:crc32(L) end, 116 CRC32_2 = fun(L) -> ?REF:crc32(L) end, 117 ADLER32_1 = fun(L) -> erlang:adler32(L) end, 118 ADLER32_2 = fun(L) -> ?REF:adler32(L) end, 119 MD5_1 = fun(L) -> erlang:md5(L) end, 120 MD5_2 = fun(L) -> ?REF:md5_final( 121 ?REF:md5_update(?REF:md5_init(),L)) end, 122 MD5_3 = fun(L) -> erlang:md5_final( 123 erlang:md5_update(erlang:md5_init(),L)) end, 124 CRC32_1_L = fun(L) -> erlang:crc32([B|L]) end, 125 CRC32_2_L = fun(L) -> ?REF:crc32([B|L]) end, 126 ADLER32_1_L = fun(L) -> erlang:adler32([B|L]) end, 127 ADLER32_2_L = fun(L) -> ?REF:adler32([B|L]) end, 128 MD5_1_L = fun(L) -> erlang:md5([B|L]) end, 129 MD5_2_L = fun(L) -> ?REF:md5_final( 130 ?REF:md5_update(?REF:md5_init(),[B|L])) end, 131 MD5_3_L = fun(L) -> erlang:md5_final( 132 erlang:md5_update( 133 erlang:md5_init(),[B|L])) end, 134 Wlist0 = 135 [{?LINE, fun() -> random_iolist:run(150, CRC32_1, CRC32_2) end}, 136 {?LINE, fun() -> random_iolist:run(150, ADLER32_1, ADLER32_2) end}, 137 {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_2) end}, 138 {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_3) end}, 139 {?LINE, fun() -> random_iolist:run(150, CRC32_1_L, CRC32_2_L) end}, 140 {?LINE, 141 fun() -> random_iolist:run(150, ADLER32_1_L, ADLER32_2_L) end}, 142 {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_2_L) end}, 143 {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_3_L) end}], 144 run_in_para(Wlist0,Num), 145 CRC32_1_2 = fun(L1,L2) -> erlang:crc32([L1,L2]) end, 146 CRC32_2_2 = fun(L1,L2) -> erlang:crc32(erlang:crc32(L1),L2) end, 147 CRC32_3_2 = fun(L1,L2) -> erlang:crc32_combine( 148 erlang:crc32(L1), 149 erlang:crc32(L2), 150 erlang:iolist_size(L2)) 151 end, 152 ADLER32_1_2 = fun(L1,L2) -> erlang:adler32([L1,L2]) end, 153 ADLER32_2_2 = fun(L1,L2) -> erlang:adler32( 154 erlang:adler32(L1),L2) end, 155 ADLER32_3_2 = fun(L1,L2) -> erlang:adler32_combine( 156 erlang:adler32(L1), 157 erlang:adler32(L2), 158 erlang:iolist_size(L2)) 159 end, 160 MD5_1_2 = fun(L1,L2) -> erlang:md5([L1,L2]) end, 161 MD5_2_2 = fun(L1,L2) -> 162 erlang:md5_final( 163 erlang:md5_update( 164 erlang:md5_update( 165 erlang:md5_init(), 166 L1), 167 L2)) 168 end, 169 CRC32_1_L_2 = fun(L1,L2) -> erlang:crc32([[B|L1],[B|L2]]) end, 170 CRC32_2_L_2 = fun(L1,L2) -> erlang:crc32( 171 erlang:crc32([B|L1]),[B|L2]) end, 172 CRC32_3_L_2 = fun(L1,L2) -> erlang:crc32_combine( 173 erlang:crc32([B|L1]), 174 erlang:crc32([B|L2]), 175 erlang:iolist_size([B|L2])) 176 end, 177 ADLER32_1_L_2 = fun(L1,L2) -> erlang:adler32([[B|L1],[B|L2]]) end, 178 ADLER32_2_L_2 = fun(L1,L2) -> erlang:adler32( 179 erlang:adler32([B|L1]), 180 [B|L2]) 181 end, 182 ADLER32_3_L_2 = fun(L1,L2) -> erlang:adler32_combine( 183 erlang:adler32([B|L1]), 184 erlang:adler32([B|L2]), 185 erlang:iolist_size([B|L2])) 186 end, 187 MD5_1_L_2 = fun(L1,L2) -> erlang:md5([[B|L1],[B|L2]]) end, 188 MD5_2_L_2 = fun(L1,L2) -> 189 erlang:md5_final( 190 erlang:md5_update( 191 erlang:md5_update( 192 erlang:md5_init(), 193 [B|L1]), 194 [B|L2])) 195 end, 196 Wlist1 = 197 [{?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_2_2) end}, 198 {?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_3_2) end}, 199 {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_2_2) end}, 200 {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_3_2) end}, 201 {?LINE, fun() -> random_iolist:run2(150,MD5_1_2,MD5_2_2) end}, 202 {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_2_L_2) end}, 203 {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_3_L_2) end}, 204 {?LINE, 205 fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_2_L_2) end}, 206 {?LINE, 207 fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_3_L_2) end}, 208 {?LINE, fun() -> random_iolist:run2(150,MD5_1_L_2,MD5_2_L_2) end}], 209 run_in_para(Wlist1,Num), 210 ok. 211 212%% Generate MD5 message digests and check the result. Examples are from RFC-1321. 213t_md5(Config) when is_list(Config) -> 214 t_md5_test("", "d41d8cd98f00b204e9800998ecf8427e"), 215 t_md5_test("a", "0cc175b9c0f1b6a831c399e269772661"), 216 t_md5_test("abc", "900150983cd24fb0d6963f7d28e17f72"), 217 t_md5_test(["message ","digest"], "f96b697d7cb7938d525a2f31aaf161d0"), 218 t_md5_test(["message ",unaligned_sub_bin(<<"digest">>)], 219 "f96b697d7cb7938d525a2f31aaf161d0"), 220 t_md5_test("abcdefghijklmnopqrstuvwxyz", 221 "c3fcd3d76192e4007dfb496cca67e13b"), 222 t_md5_test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 223 "0123456789", 224 "d174ab98d277d9f5a5611c2c9f419d9f"), 225 t_md5_test("12345678901234567890123456789012345678901234567890" 226 "123456789012345678901234567890", 227 "57edf4a22be3c955ac49da2e2107b67a"), 228 ok. 229 230%% Generate MD5 message using md5_init, md5_update, and md5_final, and 231%% check the result. Examples are from RFC-1321. 232t_md5_update(Config) when is_list(Config) -> 233 t_md5_update_1(fun(Str) -> Str end), 234 t_md5_update_1(fun(Str) -> list_to_binary(Str) end), 235 t_md5_update_1(fun(Str) -> unaligned_sub_bin(list_to_binary(Str)) end), 236 ok. 237 238t_md5_update_1(Tr) when is_function(Tr, 1) -> 239 Ctx = erlang:md5_init(), 240 Ctx1 = erlang:md5_update(Ctx, Tr("ABCDEFGHIJKLMNOPQRSTUVWXYZ")), 241 Ctx2 = erlang:md5_update(Ctx1, Tr("abcdefghijklmnopqrstuvwxyz" 242 "0123456789")), 243 m(erlang:md5_final(Ctx2), 244 hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), 245 ok. 246 247%% 248%% 249error(Config) when is_list(Config) -> 250 {'EXIT',{badarg,_}} = (catch erlang:md5(bit_sized_binary(<<"abc">>))), 251 Ctx0 = erlang:md5_init(), 252 {'EXIT',{badarg,_}} = 253 (catch erlang:md5_update(Ctx0, bit_sized_binary(<<"abcfjldjd">>))), 254 {'EXIT',{badarg,_}} = 255 (catch erlang:md5_update(Ctx0, ["something",bit_sized_binary(<<"abcfjldjd">>)])), 256 {'EXIT',{badarg,_}} = 257 (catch erlang:md5_update(bit_sized_binary(Ctx0), "something")), 258 {'EXIT',{badarg,_}} = (catch erlang:md5_final(bit_sized_binary(Ctx0))), 259 m(erlang:md5_final(Ctx0), hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")), 260 ok. 261 262 263%% 264%% 265unaligned_context(Config) when is_list(Config) -> 266 Ctx0 = erlang:md5_init(), 267 Ctx1 = erlang:md5_update(unaligned_sub_bin(Ctx0), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 268 Ctx = erlang:md5_update(unaligned_sub_bin(Ctx1), 269 "abcdefghijklmnopqrstuvwxyz0123456789"), 270 m(erlang:md5_final(unaligned_sub_bin(Ctx)), 271 hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), 272 ok. 273 274%% 275%% Help functions 276%% 277 278t_md5_test(Str, ResultStr) -> 279 ResultBin = hexstr2bin(ResultStr), 280 m(erlang:md5(Str), ResultBin), 281 Bin = list_to_binary(Str), 282 m(erlang:md5(Bin), ResultBin), 283 UnalignedSubBin = unaligned_sub_bin(Bin), 284 m(erlang:md5(UnalignedSubBin), ResultBin). 285 286m(X, X) -> true. 287 288hexstr2bin(S) -> 289 list_to_binary(hexstr2list(S)). 290 291hexstr2list([X,Y|T]) -> 292 [mkint(X)*16 + mkint(Y) | hexstr2list(T)]; 293hexstr2list([]) -> 294 []. 295 296mkint(C) when $0 =< C, C =< $9 -> 297 C - $0; 298mkint(C) when $A =< C, C =< $F -> 299 C - $A + 10; 300mkint(C) when $a =< C, C =< $f -> 301 C - $a + 10. 302 303unaligned_sub_bin(Bin0) -> 304 Bin1 = <<0:3,Bin0/binary,31:5>>, 305 Sz = size(Bin0), 306 <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), 307 Bin. 308 309%% Add 1 bit to the size of the binary. 310bit_sized_binary(Bin0) -> 311 Bin = <<Bin0/binary,1:1>>, 312 BitSize = bit_size(Bin), 313 BitSize = 8*size(Bin) + 1, 314 Bin. 315 316id(I) -> I. 317