|
1 | 1 | -module(pbkdf2_eqc). |
2 | 2 |
|
| 3 | +%% Compile C code and compare C code execution with Erlang code. |
| 4 | + |
3 | 5 | -export([prop_equivalent/0]). |
4 | 6 |
|
5 | 7 | -include_lib("eqc/include/eqc.hrl"). |
|
9 | 11 | eqc:on_output(fun(Str, Args) -> io:format(user, Str, Args) end, P)). |
10 | 12 |
|
11 | 13 | eqc_test_() -> |
12 | | - {timeout, 30, |
13 | | - [ |
14 | | - {timeout, 30, ?_assertEqual(true, eqc:quickcheck(eqc:testing_time(14, ?QC_OUT(prop_equivalent()))))} |
15 | | - ] |
16 | | - }. |
| 14 | + {timeout, 30, |
| 15 | + [ |
| 16 | + {timeout, 30, ?_assertEqual(true, eqc:quickcheck(eqc:testing_time(14, ?QC_OUT(prop_equivalent()))))} |
| 17 | + ] |
| 18 | + }. |
17 | 19 |
|
18 | 20 | prop_equivalent() -> |
19 | | - %% try to compile the openssl port we need to compare the erlang version against: |
20 | | - case code:lib_dir(erl_interface) of |
21 | | - {error, Reason} -> |
22 | | - {error, Reason}; |
23 | | - EIDir -> |
24 | | - %% we assume the ebin of this file is in .eunit, where rebar puts it |
25 | | - PortSrcDir = "eqc", |
26 | | - %% yeeehaw |
27 | | - [] = os:cmd("gcc -Wno-format -Wno-pointer-sign -Wno-implicit-function-declaration "++PortSrcDir++"/pbkdf2-port.c -o pbkdf2-port -I"++EIDir++"/include -L"++EIDir++"/lib -lei -lssl -lcrypto"), |
28 | | - ?FORALL({Password, Salt, Iterations, KeySize}, {gen_print_bin(), gen_salt(), gen_iterations(), gen_keysize()}, |
29 | | - begin |
30 | | - Port = open_port({spawn, "./pbkdf2-port"}, [{packet, 4}]), |
31 | | - Hash = sha, %% only hash openssl supports for PBKDF2 is SHA1 :( |
32 | | - {ok, Bin} = pbkdf2:pbkdf2(Hash, Password, Salt, Iterations, KeySize), |
33 | | - Result = pbkdf2:to_hex(Bin), |
34 | | - port_command(Port, term_to_binary({Hash, Password, Salt, Iterations, KeySize})), |
35 | | - Expected = receive |
36 | | - {Port, {data, E}} -> |
37 | | - list_to_binary(E) |
38 | | - after |
39 | | - 5000 -> |
40 | | - timeout |
41 | | - end, |
42 | | - port_close(Port), |
43 | | - ?WHENFAIL(begin |
44 | | - io:format(user, "Password ~p~n", [Password]), |
45 | | - io:format(user, "Salt ~p~n", [Salt]), |
46 | | - io:format(user, "Iterations ~p~n", [Iterations]), |
47 | | - io:format(user, "KeySize ~p~n", [KeySize]), |
48 | | - io:format(user, "Expected ~p~n", [Expected]), |
49 | | - io:format(user, "Result ~p~n", [Result]) |
50 | | - end, |
51 | | - Expected == Result) |
52 | | - end) |
53 | | - end. |
| 21 | + ?SETUP(fun() -> |
| 22 | + ok = compile_c_code(), |
| 23 | + fun(_) -> ok end |
| 24 | + end, |
| 25 | + ?FORALL({Password, Salt, Iterations, KeySize}, {gen_print_bin(), gen_salt(), gen_iterations(), gen_keysize()}, |
| 26 | + begin |
| 27 | + Port = open_port({spawn, "./pbkdf2-port"}, [{packet, 4}]), |
| 28 | + Hash = sha, %% only hash openssl supports for PBKDF2 is SHA1 :( |
| 29 | + {ok, Bin} = pbkdf2:pbkdf2(Hash, Password, Salt, Iterations, KeySize), |
| 30 | + Result = pbkdf2:to_hex(Bin), |
| 31 | + port_command(Port, term_to_binary({Hash, Password, Salt, Iterations, KeySize})), |
| 32 | + Expected = receive |
| 33 | + {Port, {data, E}} -> |
| 34 | + list_to_binary(E) |
| 35 | + after |
| 36 | + 5000 -> |
| 37 | + timeout |
| 38 | + end, |
| 39 | + port_close(Port), |
| 40 | + ?WHENFAIL(begin |
| 41 | + io:format(user, "Password ~p~n", [Password]), |
| 42 | + io:format(user, "Salt ~p~n", [Salt]), |
| 43 | + io:format(user, "Iterations ~p~n", [Iterations]), |
| 44 | + io:format(user, "KeySize ~p~n", [KeySize]), |
| 45 | + io:format(user, "Expected ~p~n", [Expected]), |
| 46 | + io:format(user, "Result ~p~n", [Result]) |
| 47 | + end, |
| 48 | + Expected == Result) |
| 49 | + end)). |
| 50 | + |
| 51 | +compile_c_code() -> |
| 52 | + %% try to compile the openssl port we need to compare the erlang version against: |
| 53 | + case code:lib_dir(erl_interface) of |
| 54 | + {error, Reason} -> |
| 55 | + {error, Reason}; |
| 56 | + EIDir -> |
| 57 | + %% EIDir is the erl_interface dir which contains lib and include for erl_interface C code |
| 58 | + PortSrcDir = "./eqc", |
| 59 | + %% yeeehaw |
| 60 | + case os:cmd("gcc -Wno-format -Wno-pointer-sign -Wno-implicit-function-declaration "++PortSrcDir++"/pbkdf2-port.c -o pbkdf2-port -I"++EIDir++"/include -L"++EIDir++"/lib -lei -lssl -lcrypto") of |
| 61 | + [] -> |
| 62 | + ok; |
| 63 | + Error -> |
| 64 | + %% We need access to include files like openssl/evp.h |
| 65 | + {error, {compiling_c_code, Error}} |
| 66 | + end |
| 67 | + end. |
54 | 68 |
|
55 | 69 | gen_print_str() -> |
56 | | - ?LET(Xs, list(char()), [X || X <- Xs, io_lib:printable_list([X]), X /= $~, X < 255]). |
| 70 | + ?LET(Xs, list(char()), [X || X <- Xs, io_lib:printable_list([X]), X /= $~, X < 255]). |
57 | 71 |
|
58 | 72 | gen_print_bin() -> |
59 | | - ?SUCHTHAT(B, ?LET(Xs, gen_print_str(), list_to_binary(Xs)), B/= <<>>). |
| 73 | + ?SUCHTHAT(B, ?LET(Xs, gen_print_str(), list_to_binary(Xs)), B/= <<>>). |
60 | 74 |
|
61 | 75 | gen_salt() -> |
62 | | - ?SUCHTHAT(S, binary(), S /= <<>>). |
| 76 | + ?SUCHTHAT(S, binary(), S /= <<>>). |
63 | 77 |
|
64 | 78 | gen_keysize() -> |
65 | | - ?LET(Xs, nat(), Xs+5). |
| 79 | + ?LET(Xs, nat(), Xs+5). |
66 | 80 |
|
67 | 81 | gen_iterations() -> |
68 | | - ?LET(X, ?SUCHTHAT(I, nat(), I > 0), X*X). |
| 82 | + ?LET(X, ?SUCHTHAT(I, nat(), I > 0), X*X). |
0 commit comments