%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1999-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% -module(crypto_SUITE). -include_lib("common_test/include/ct.hrl"). -export([all/0, suite/0, t_md5/1,t_md5_update/1,error/1,unaligned_context/1,random_lists/1, misc_errors/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [t_md5, t_md5_update, error, unaligned_context, random_lists, misc_errors]. %% Test crc32, adler32 and md5 error cases not covered by other tests" misc_errors(Config) when is_list(Config) -> ct:timetrap({minutes, 2}), 1 = erlang:adler32([]), L = lists:duplicate(600,3), 1135871753 = erlang:adler32(L), L2 = lists:duplicate(22000,3), 1100939744 = erlang:adler32(L2), {'EXIT', {badarg,_}} = (catch erlang:adler32(L++[a])), {'EXIT', {badarg,_}} = (catch erlang:crc32(L++[a])), {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|<<25:7>>])), {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|4])), Big = 111111111111111111111111111111, {'EXIT', {badarg,_}} = (catch erlang:crc32(Big,<<"hej">>)), {'EXIT', {badarg,_}} = (catch erlang:crc32(25,[1,2,3|4])), {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(Big,3,3)), {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,Big,3)), {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,3,Big)), {'EXIT', {badarg,_}} = (catch erlang:adler32(Big,<<"hej">>)), {'EXIT', {badarg,_}} = (catch erlang:adler32(25,[1,2,3|4])), {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(Big,3,3)), {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,Big,3)), {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,3,Big)), {'EXIT', {badarg,_}} = (catch erlang:md5_update(<<"hej">>,<<"hej">>)), {'EXIT', {badarg,_}} = (catch erlang:md5_final(<<"hej">>)), ok. %% %% Most of the real code for these test cases are in %% the modules crypto_reference and random_iolist. %% -define(REF,crypto_reference). nicesplit(N,L) -> nicesplit(N,L,[]). nicesplit(0,Tail,Acc) -> {lists:reverse(Acc),Tail}; nicesplit(_,[],Acc) -> {lists:reverse(Acc),[]}; nicesplit(N,[H|Tail],Acc) -> nicesplit(N-1,Tail,[H|Acc]). run_in_para([],_) -> true; run_in_para(FunList,Schedulers) -> {ThisTime,NextTime} = nicesplit(Schedulers,FunList), case length(ThisTime) of 1 -> [{L,Fun}] = ThisTime, try Fun() catch _:Reason -> exit({error_at_line,L,Reason}) end; _ -> These = [ {L,erlang:spawn_monitor(F)} || {L,F} <- ThisTime ], collect_workers(These) end, run_in_para(NextTime,Schedulers). collect_workers([]) -> ok; collect_workers([{L,{Pid,Ref}}|T]) -> receive {'DOWN',Ref,process,Pid,normal} -> collect_workers(T); {'DOWN',Ref,process,Pid,Other} -> exit({error_at_line,L,Other}) end. %% Test crc32, adler32 and md5 on a number of pseudo-randomly generated lists. random_lists(Config) when is_list(Config) -> ct:timetrap({minutes, 5}), Num = erlang:system_info(schedulers_online), B = list_to_binary( lists:duplicate( (erlang:system_info(context_reductions)*10) - 50,$!)), CRC32_1 = fun(L) -> erlang:crc32(L) end, CRC32_2 = fun(L) -> ?REF:crc32(L) end, ADLER32_1 = fun(L) -> erlang:adler32(L) end, ADLER32_2 = fun(L) -> ?REF:adler32(L) end, MD5_1 = fun(L) -> erlang:md5(L) end, MD5_2 = fun(L) -> ?REF:md5_final( ?REF:md5_update(?REF:md5_init(),L)) end, MD5_3 = fun(L) -> erlang:md5_final( erlang:md5_update(erlang:md5_init(),L)) end, CRC32_1_L = fun(L) -> erlang:crc32([B|L]) end, CRC32_2_L = fun(L) -> ?REF:crc32([B|L]) end, ADLER32_1_L = fun(L) -> erlang:adler32([B|L]) end, ADLER32_2_L = fun(L) -> ?REF:adler32([B|L]) end, MD5_1_L = fun(L) -> erlang:md5([B|L]) end, MD5_2_L = fun(L) -> ?REF:md5_final( ?REF:md5_update(?REF:md5_init(),[B|L])) end, MD5_3_L = fun(L) -> erlang:md5_final( erlang:md5_update( erlang:md5_init(),[B|L])) end, Wlist0 = [{?LINE, fun() -> random_iolist:run(150, CRC32_1, CRC32_2) end}, {?LINE, fun() -> random_iolist:run(150, ADLER32_1, ADLER32_2) end}, {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_2) end}, {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_3) end}, {?LINE, fun() -> random_iolist:run(150, CRC32_1_L, CRC32_2_L) end}, {?LINE, fun() -> random_iolist:run(150, ADLER32_1_L, ADLER32_2_L) end}, {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_2_L) end}, {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_3_L) end}], run_in_para(Wlist0,Num), CRC32_1_2 = fun(L1,L2) -> erlang:crc32([L1,L2]) end, CRC32_2_2 = fun(L1,L2) -> erlang:crc32(erlang:crc32(L1),L2) end, CRC32_3_2 = fun(L1,L2) -> erlang:crc32_combine( erlang:crc32(L1), erlang:crc32(L2), erlang:iolist_size(L2)) end, ADLER32_1_2 = fun(L1,L2) -> erlang:adler32([L1,L2]) end, ADLER32_2_2 = fun(L1,L2) -> erlang:adler32( erlang:adler32(L1),L2) end, ADLER32_3_2 = fun(L1,L2) -> erlang:adler32_combine( erlang:adler32(L1), erlang:adler32(L2), erlang:iolist_size(L2)) end, MD5_1_2 = fun(L1,L2) -> erlang:md5([L1,L2]) end, MD5_2_2 = fun(L1,L2) -> erlang:md5_final( erlang:md5_update( erlang:md5_update( erlang:md5_init(), L1), L2)) end, CRC32_1_L_2 = fun(L1,L2) -> erlang:crc32([[B|L1],[B|L2]]) end, CRC32_2_L_2 = fun(L1,L2) -> erlang:crc32( erlang:crc32([B|L1]),[B|L2]) end, CRC32_3_L_2 = fun(L1,L2) -> erlang:crc32_combine( erlang:crc32([B|L1]), erlang:crc32([B|L2]), erlang:iolist_size([B|L2])) end, ADLER32_1_L_2 = fun(L1,L2) -> erlang:adler32([[B|L1],[B|L2]]) end, ADLER32_2_L_2 = fun(L1,L2) -> erlang:adler32( erlang:adler32([B|L1]), [B|L2]) end, ADLER32_3_L_2 = fun(L1,L2) -> erlang:adler32_combine( erlang:adler32([B|L1]), erlang:adler32([B|L2]), erlang:iolist_size([B|L2])) end, MD5_1_L_2 = fun(L1,L2) -> erlang:md5([[B|L1],[B|L2]]) end, MD5_2_L_2 = fun(L1,L2) -> erlang:md5_final( erlang:md5_update( erlang:md5_update( erlang:md5_init(), [B|L1]), [B|L2])) end, Wlist1 = [{?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_2_2) end}, {?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_3_2) end}, {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_2_2) end}, {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_3_2) end}, {?LINE, fun() -> random_iolist:run2(150,MD5_1_2,MD5_2_2) end}, {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_2_L_2) end}, {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_3_L_2) end}, {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_2_L_2) end}, {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_3_L_2) end}, {?LINE, fun() -> random_iolist:run2(150,MD5_1_L_2,MD5_2_L_2) end}], run_in_para(Wlist1,Num), ok. %% Generate MD5 message digests and check the result. Examples are from RFC-1321. t_md5(Config) when is_list(Config) -> t_md5_test("", "d41d8cd98f00b204e9800998ecf8427e"), t_md5_test("a", "0cc175b9c0f1b6a831c399e269772661"), t_md5_test("abc", "900150983cd24fb0d6963f7d28e17f72"), t_md5_test(["message ","digest"], "f96b697d7cb7938d525a2f31aaf161d0"), t_md5_test(["message ",unaligned_sub_bin(<<"digest">>)], "f96b697d7cb7938d525a2f31aaf161d0"), t_md5_test("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"), t_md5_test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"), t_md5_test("12345678901234567890123456789012345678901234567890" "123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"), ok. %% Generate MD5 message using md5_init, md5_update, and md5_final, and %% check the result. Examples are from RFC-1321. t_md5_update(Config) when is_list(Config) -> t_md5_update_1(fun(Str) -> Str end), t_md5_update_1(fun(Str) -> list_to_binary(Str) end), t_md5_update_1(fun(Str) -> unaligned_sub_bin(list_to_binary(Str)) end), ok. t_md5_update_1(Tr) when is_function(Tr, 1) -> Ctx = erlang:md5_init(), Ctx1 = erlang:md5_update(Ctx, Tr("ABCDEFGHIJKLMNOPQRSTUVWXYZ")), Ctx2 = erlang:md5_update(Ctx1, Tr("abcdefghijklmnopqrstuvwxyz" "0123456789")), m(erlang:md5_final(Ctx2), hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), ok. %% %% error(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch erlang:md5(bit_sized_binary(<<"abc">>))), Ctx0 = erlang:md5_init(), {'EXIT',{badarg,_}} = (catch erlang:md5_update(Ctx0, bit_sized_binary(<<"abcfjldjd">>))), {'EXIT',{badarg,_}} = (catch erlang:md5_update(Ctx0, ["something",bit_sized_binary(<<"abcfjldjd">>)])), {'EXIT',{badarg,_}} = (catch erlang:md5_update(bit_sized_binary(Ctx0), "something")), {'EXIT',{badarg,_}} = (catch erlang:md5_final(bit_sized_binary(Ctx0))), m(erlang:md5_final(Ctx0), hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")), ok. %% %% unaligned_context(Config) when is_list(Config) -> Ctx0 = erlang:md5_init(), Ctx1 = erlang:md5_update(unaligned_sub_bin(Ctx0), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), Ctx = erlang:md5_update(unaligned_sub_bin(Ctx1), "abcdefghijklmnopqrstuvwxyz0123456789"), m(erlang:md5_final(unaligned_sub_bin(Ctx)), hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), ok. %% %% Help functions %% t_md5_test(Str, ResultStr) -> ResultBin = hexstr2bin(ResultStr), m(erlang:md5(Str), ResultBin), Bin = list_to_binary(Str), m(erlang:md5(Bin), ResultBin), UnalignedSubBin = unaligned_sub_bin(Bin), m(erlang:md5(UnalignedSubBin), ResultBin). m(X, X) -> true. hexstr2bin(S) -> list_to_binary(hexstr2list(S)). hexstr2list([X,Y|T]) -> [mkint(X)*16 + mkint(Y) | hexstr2list(T)]; hexstr2list([]) -> []. mkint(C) when $0 =< C, C =< $9 -> C - $0; mkint(C) when $A =< C, C =< $F -> C - $A + 10; mkint(C) when $a =< C, C =< $f -> C - $a + 10. unaligned_sub_bin(Bin0) -> Bin1 = <<0:3,Bin0/binary,31:5>>, Sz = size(Bin0), <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), Bin. %% Add 1 bit to the size of the binary. bit_sized_binary(Bin0) -> Bin = <<Bin0/binary,1:1>>, BitSize = bit_size(Bin), BitSize = 8*size(Bin) + 1, Bin. id(I) -> I.