Move functions around. Mark untested functionality.

A lot of people who pushed functions they missed have not pushed any
kind of test cases for them. To make sure we have test coverage, I've
marked the functions we have under test and the functions we are still
missing tests for.
This commit is contained in:
Jesper Louis Andersen 2018-05-21 12:27:24 +02:00
parent 75042a24ba
commit 3b9bc848e9
3 changed files with 185 additions and 165 deletions

View File

@ -124,7 +124,11 @@ keypair() ->
%% CRYPTO BOX
%% ---------------------------
%% * box/4
%% * box_open/4
%% * box_beforenm/2
%% * box_afternm/3
%% * box_open_afternm/3
keypair_valid(PK, SK) when is_binary(PK), is_binary(SK) ->
PKBytes = enacl:box_public_key_bytes(),
SKBytes = enacl:box_secret_key_bytes(),
@ -220,40 +224,6 @@ prop_box_failure_integrity() ->
end
end).
prop_seal_box_failure_integrity() ->
?FORALL({Msg, {PK1, SK1}}, {?FAULT_RATE(1,40,g_iodata()), ?FAULT_RATE(1,40,keypair())},
begin
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
CT = enacl:box_seal(Msg, PK1),
Err = enacl:box_seal_open([<<"x">>, CT], PK1, SK1),
equals(Err, {error, failed_verification});
false ->
case box_seal(Msg, PK1) of
badarg -> true;
Res ->
failure(box_seal_open(Res, PK1, SK1))
end
end
end).
prop_seal_box_correct() ->
?FORALL({Msg, {PK1, SK1}},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, keypair())},
begin
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
SealedCipherText = enacl:box_seal(Msg, PK1),
{ok, DecodedMsg} = enacl:box_seal_open(SealedCipherText, PK1, SK1),
equals(iolist_to_binary(Msg), DecodedMsg);
false ->
case box_seal(Msg, PK1) of
badarg -> true;
Res -> failure(box_seal_open(Res, PK1, SK1))
end
end
end).
%% PRECOMPUTATIONS
beforenm_key() ->
@ -456,67 +426,46 @@ prop_sign_open() ->
badargs(fun() -> enacl:sign_open(SignMsg, PK) end)
end)).
%% PWHASH
%% -------------------------------
pwhash(Passwd, Salt) ->
try
enacl:pwhash(Passwd, Salt)
catch
error:badarg -> badarg
end.
pwhash_str(Passwd) ->
try
enacl:pwhash_str(Passwd)
catch
error:badarg -> badarg
end.
pwhash_str_verify(PasswdHash, Passwd) ->
try
enacl:pwhash_str_verify(PasswdHash, Passwd)
catch
error:badarg -> badarg
end.
prop_pwhash_str_verify() ->
?FORALL({Passwd},
{?FAULT_RATE(1, 40, g_iodata())},
prop_seal_box_failure_integrity() ->
?FORALL({Msg, {PK1, SK1}}, {?FAULT_RATE(1,40,g_iodata()), ?FAULT_RATE(1,40,keypair())},
begin
case v_iodata(Passwd) of
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
{ok, Ascii} = enacl:pwhash_str(Passwd),
S = enacl:pwhash_str_verify(Ascii, Passwd),
equals(S, true);
CT = enacl:box_seal(Msg, PK1),
Err = enacl:box_seal_open([<<"x">>, CT], PK1, SK1),
equals(Err, {error, failed_verification});
false ->
badargs(fun() -> enacl:pwhash_str(Passwd) end),
badargs(fun() -> enacl:pwhash_str_verify("", Passwd) end)
case box_seal(Msg, PK1) of
badarg -> true;
Res ->
failure(box_seal_open(Res, PK1, SK1))
end
end
end).
prop_seal_box_correct() ->
?FORALL({Msg, {PK1, SK1}},
{?FAULT_RATE(1, 40, g_iodata()),
?FAULT_RATE(1, 40, keypair())},
begin
case v_iodata(Msg) andalso keypair_valid(PK1, SK1) of
true ->
SealedCipherText = enacl:box_seal(Msg, PK1),
{ok, DecodedMsg} = enacl:box_seal_open(SealedCipherText, PK1, SK1),
equals(iolist_to_binary(Msg), DecodedMsg);
false ->
case box_seal(Msg, PK1) of
badarg -> true;
Res -> failure(box_seal_open(Res, PK1, SK1))
end
end
end).
%% CRYPTO SECRET BOX
%% -------------------------------
%% Note: key sizes are the same in a lot of situations, so we can use the same generator
%% for keys in many locations.
key_sz(Sz) ->
equals(enacl:secretbox_key_size(), Sz).
%% prop_key_sizes() ->
%% conjunction([{secret, key_sz(enacl:secretbox_key_size())},
%% {stream, key_sz(enacl:stream_key_size())},
%% {auth, key_sz(enacl:auth_key_size())},
%% {onetimeauth, key_sz(enacl:onetime_auth_key_size())}]).
nonce_sz(Sz) ->
equals(enacl:secretbox_nonce_size(), Sz).
%% prop_nonce_sizes() ->
%% conjunction([{secret, nonce_sz(enacl:secretbox_nonce_size())},
%% {stream, nonce_sz(enacl:stream_nonce_size())}]).
%% ------------------------------------------------------------
%% * secretbox/3
%% * secretbo_open/3
secret_key_good() ->
Sz = enacl:secretbox_key_size(),
binary(Sz).
@ -535,17 +484,13 @@ secret_key_valid(SK) when is_binary(SK) ->
secret_key_valid(_SK) -> false.
secretbox(Msg, Nonce, Key) ->
try
enacl:secretbox(Msg, Nonce, Key)
catch
error:badarg -> badarg
try enacl:secretbox(Msg, Nonce, Key)
catch error:badarg -> badarg
end.
secretbox_open(Msg, Nonce, Key) ->
try
enacl:secretbox_open(Msg, Nonce, Key)
catch
error:badarg -> badarg
try enacl:secretbox_open(Msg, Nonce, Key)
catch error:badarg -> badarg
end.
prop_secretbox_correct() ->
@ -576,7 +521,32 @@ prop_secretbox_failure_integrity() ->
equals(Err, {error, failed_verification})
end).
%% AEAD ChaCha20Poly1305
%% ------------------------------------------------------------
%% * aead_chacha20poly1305_encrypt/4,
%% * aead_chacha20poly1305_decrypt/4,
prop_aead_chacha20poly1305() ->
?FORALL({Key, Msg, AD, Nonce},
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
begin
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
equals(enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, EncryptMsg), Msg)
end).
prop_aead_chacha20poly1305_fail() ->
?FORALL({Key, Msg, AD, Nonce},
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
begin
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
case enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, <<0:8, EncryptMsg/binary>>) of
{error, _} -> true;
_ -> false
end
end).
%% CRYPTO STREAM
%% ------------------------------------------------------------
%% * stream/3
prop_stream_correct() ->
?FORALL({Len, Nonce, Key},
{int(),
@ -613,6 +583,9 @@ xor_bytes(<<>>, <<>>) -> [].
%% end).
%% CRYPTO AUTH
%% ------------------------------------------------------------
%% * auth/2
%% * auth_verify/3
prop_auth_correct() ->
?FORALL({Msg, Key},
{?FAULT_RATE(1, 40, g_iodata()),
@ -665,6 +638,9 @@ prop_auth_verify_correct() ->
end)).
%% CRYPTO ONETIME AUTH
%% ------------------------------------------------------------
%% * onetime_auth/2
%% * onetime_auth_verify/3
prop_onetimeauth_correct() ->
?FORALL({Msg, Key},
{?FAULT_RATE(1, 40, g_iodata()),
@ -716,7 +692,48 @@ prop_onetime_auth_verify_correct() ->
badargs(fun() -> enacl:onetime_auth_verify(Authenticator, Msg, Key) end)
end)).
%% HASHING
%% PWHASH
%% -------------------------------
%% * pwhash/2
%% * pwhash_str/1
%% * pwhash_str_verify/2
pwhash(Passwd, Salt) ->
try
enacl:pwhash(Passwd, Salt)
catch
error:badarg -> badarg
end.
pwhash_str(Passwd) ->
try
enacl:pwhash_str(Passwd)
catch
error:badarg -> badarg
end.
pwhash_str_verify(PasswdHash, Passwd) ->
try
enacl:pwhash_str_verify(PasswdHash, Passwd)
catch
error:badarg -> badarg
end.
prop_pwhash_str_verify() ->
?FORALL({Passwd},
{?FAULT_RATE(1, 40, g_iodata())},
begin
case v_iodata(Passwd) of
true ->
{ok, Ascii} = enacl:pwhash_str(Passwd),
S = enacl:pwhash_str_verify(Ascii, Passwd),
equals(S, true);
false ->
badargs(fun() -> enacl:pwhash_str(Passwd) end),
badargs(fun() -> enacl:pwhash_str_verify("", Passwd) end)
end
end).
%% SUBTLE HASHING
%% ---------------------------
diff_pair() ->
?SUCHTHAT({X, Y}, {g_iodata(), g_iodata()},
@ -743,7 +760,8 @@ prop_crypto_hash_neq() ->
%% STRING COMPARISON
%% -------------------------
%% * verify_16/2,
%% * verify_32/2
verify_pair_bad(Sz) ->
?LET(X, elements([fst, snd]),
case X of
@ -793,6 +811,8 @@ prop_verify_32() ->
end).
%% RANDOMBYTES
%% ------------------------------------------------------------
%% * randombytes/1
prop_randombytes() ->
?FORALL(X, g_nat(),
case is_nat(X) of
@ -808,12 +828,8 @@ prop_randombytes() ->
end
end).
%% SCRAMBLING
prop_scramble_block() ->
?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)},
is_binary(enacl_ext:scramble_block_16(Block, Key))).
%% HELPERS
%% INTERNAL FUNCTIONS
%% ------------------------------------------------------------
badargs(Thunk) ->
try
Thunk(),
@ -822,26 +838,6 @@ badargs(Thunk) ->
error:badarg -> true
end.
%% AEAD ChaCha20Poly1305
prop_aead_chacha20poly1305() ->
?FORALL({Key, Msg, AD, Nonce},
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
begin
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
equals(enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, EncryptMsg), Msg)
end).
prop_aead_chacha20poly1305_fail() ->
?FORALL({Key, Msg, AD, Nonce},
{binary(32), binary(), ?LET(ADBytes, choose(0,16), binary(ADBytes)), largeint()},
begin
EncryptMsg = enacl:aead_chacha20poly1305_encrypt(Key, Nonce, AD, Msg),
case enacl:aead_chacha20poly1305_decrypt(Key, Nonce, AD, <<0:8, EncryptMsg/binary>>) of
{error, _} -> true;
_ -> false
end
end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Joel Test Blobs

View File

@ -22,3 +22,7 @@ prop_shared_secret() ->
equals(Alice, Bob)
end).
prop_scramble_block() ->
?FORALL({Block, Key}, {binary(16), eqc_gen:largebinary(32)},
is_binary(enacl_ext:scramble_block_16(Block, Key))).

View File

@ -18,18 +18,19 @@
%% Public key crypto
-export([
%% EQC
box_keypair/0,
box/4,
box_open/4,
box_beforenm/2,
box_afternm/3,
box_open_afternm/3,
box_nonce_size/0,
box_public_key_bytes/0,
box_secret_key_bytes/0,
box_beforenm_bytes/0,
%% EQC
sign_keypair_public_size/0,
sign_keypair_secret_size/0,
sign_keypair/0,
@ -38,22 +39,26 @@
sign_detached/2,
sign_verify_detached/3,
%% EQC
box_seal/2,
box_seal_open/3
]).
%% Secret key crypto
-export([
%% EQC
secretbox_key_size/0,
secretbox_nonce_size/0,
secretbox/3,
secretbox_open/3,
%% No Tests!
stream_chacha20_key_size/0,
stream_chacha20_nonce_size/0,
stream_chacha20/3,
stream_chacha20_xor/3,
%% EQC
aead_chacha20poly1305_encrypt/4,
aead_chacha20poly1305_decrypt/4,
aead_chacha20poly1305_KEYBYTES/0,
@ -61,34 +66,76 @@
aead_chacha20poly1305_ABYTES/0,
aead_chacha20poly1305_MESSAGEBYTES_MAX/0,
%% EQC
stream_key_size/0,
stream_nonce_size/0,
stream/3,
%% No Tests!
stream_xor/3,
%% EQC
auth_key_size/0,
auth_size/0,
auth/2,
auth_verify/3,
shorthash_key_size/0,
shorthash_size/0,
shorthash/2,
%% EQC
onetime_auth_key_size/0,
onetime_auth_size/0,
onetime_auth/2,
onetime_auth_verify/3
]).
%% Curve 25519.
%% Hash functions
-export([
%% No Tests!
generichash/3,
generichash/2,
generichash_init/2,
generichash_update/2,
generichash_final/1,
%% No Tests!
shorthash_key_size/0,
shorthash_size/0,
shorthash/2,
%% EQC
pwhash/2,
pwhash_str/1,
pwhash_str_verify/2
]).
%% Low-level subtle functions which are hard to get correct
-export([
%% EQC
hash/1,
verify_16/2,
verify_32/2,
%% No Tests!
unsafe_memzero/1
]).
%% Randomness
-export([
%% EQC
randombytes/1
]).
%%% Specific primitives
%% Curve 25519 operations.
-export([
%% No Tests!
curve25519_scalarmult/1, curve25519_scalarmult/2,
curve25519_scalarmult_base/1
]).
%% Ed 25519.
%% Ed 25519 operations.
-export([
%% No Tests!
crypto_sign_ed25519_keypair/0,
crypto_sign_ed25519_public_to_curve25519/1,
crypto_sign_ed25519_secret_to_curve25519/1,
@ -96,16 +143,9 @@
crypto_sign_ed25519_secret_size/0
]).
%% Low-level functions
-export([
hash/1,
verify_16/2,
verify_32/2,
unsafe_memzero/1
]).
%% Key exchange functions
-export([
%% No Tests!
kx_keypair/0,
kx_client_session_keys/3,
kx_server_session_keys/3,
@ -114,30 +154,10 @@
kx_session_key_size/0
]).
%% Password Hashing - Argon2 Algorithm
-export([
pwhash/2,
pwhash_str/1,
pwhash_str_verify/2
]).
%% Internal verification of the system
-export([verify/0]).
%% Generic hash functions
-export([
generichash/3,
generichash/2,
generichash_init/2,
generichash_update/2,
generichash_final/1
]).
%% Libsodium specific functions (which are also part of the "undocumented" interface to NaCl
-export([
randombytes/1
]).
-export([
verify/0
]).
%% Definitions of system budgets
%% To get a grip for these, call `enacl_timing:all/0' on your system. The numbers here are