EQC Test improvements
* Generalize binary generation because it is used again and again. * Use generalized binary generation in the hash functions since they are much faster as generators.
This commit is contained in:
parent
b109ff7834
commit
5fec48c091
@ -578,6 +578,81 @@ ERL_NIF_TERM enif_randombytes(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[
|
|||||||
return enif_make_binary(env, &result);
|
return enif_make_binary(env, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Various other helper functions */
|
||||||
|
|
||||||
|
void uint64_pack(unsigned char *y, ErlNifUInt64 x)
|
||||||
|
{
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
*y++ = x; x >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErlNifUInt64
|
||||||
|
uint64_unpack(const unsigned char *x)
|
||||||
|
{
|
||||||
|
ErlNifUInt64 result;
|
||||||
|
|
||||||
|
result = x[7];
|
||||||
|
result <<= 8; result |= x[6];
|
||||||
|
result <<= 8; result |= x[5];
|
||||||
|
result <<= 8; result |= x[4];
|
||||||
|
result <<= 8; result |= x[3];
|
||||||
|
result <<= 8; result |= x[2];
|
||||||
|
result <<= 8; result |= x[1];
|
||||||
|
result <<= 8; result |= x[0];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
crypto_block(unsigned char *out, const unsigned char *in, const unsigned char *k)
|
||||||
|
{
|
||||||
|
ErlNifUInt64 v0 = uint64_unpack(in + 0);
|
||||||
|
ErlNifUInt64 v1 = uint64_unpack(in + 8);
|
||||||
|
ErlNifUInt64 k0 = uint64_unpack(k + 0);
|
||||||
|
ErlNifUInt64 k1 = uint64_unpack(k + 8);
|
||||||
|
ErlNifUInt64 k2 = uint64_unpack(k + 16);
|
||||||
|
ErlNifUInt64 k3 = uint64_unpack(k + 24);
|
||||||
|
ErlNifUInt64 sum = 0;
|
||||||
|
ErlNifUInt64 delta = 0x9e3779b97f4a7c15;
|
||||||
|
int i;
|
||||||
|
for (i = 0;i < 32;++i) {
|
||||||
|
sum += delta;
|
||||||
|
v0 += ((v1<<7) + k0) ^ (v1 + sum) ^ ((v1>>12) + k1);
|
||||||
|
v1 += ((v0<<16) + k2) ^ (v0 + sum) ^ ((v0>>8) + k3);
|
||||||
|
}
|
||||||
|
uint64_pack(out + 0,v0);
|
||||||
|
uint64_pack(out + 8,v1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[])
|
||||||
|
{
|
||||||
|
ErlNifBinary in, out, key;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(argc != 2) ||
|
||||||
|
(!enif_inspect_binary(env, argv[0], &in)) ||
|
||||||
|
(!enif_inspect_binary(env, argv[1], &key)) ||
|
||||||
|
(in.size != 16) || (key.size != 32)) {
|
||||||
|
return enif_make_badarg(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enif_alloc_binary(in.size, &out)) {
|
||||||
|
return nacl_error_tuple(env, "alloc_failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_block(out.data, in.data, key.data);
|
||||||
|
|
||||||
|
return enif_make_binary(env, &out);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tie the knot to the Erlang world */
|
/* Tie the knot to the Erlang world */
|
||||||
static ErlNifFunc nif_funcs[] = {
|
static ErlNifFunc nif_funcs[] = {
|
||||||
{"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES},
|
{"crypto_box_NONCEBYTES", 0, enif_crypto_box_NONCEBYTES},
|
||||||
@ -635,7 +710,9 @@ static ErlNifFunc nif_funcs[] = {
|
|||||||
{"crypto_verify_32", 2, enif_crypto_verify_32},
|
{"crypto_verify_32", 2, enif_crypto_verify_32},
|
||||||
|
|
||||||
{"randombytes_b", 1, enif_randombytes},
|
{"randombytes_b", 1, enif_randombytes},
|
||||||
{"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND}
|
{"randombytes", 1, enif_randombytes, ERL_NIF_DIRTY_JOB_CPU_BOUND},
|
||||||
|
|
||||||
|
{"scramble_block_16", 2, enif_scramble_block_16}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,21 +2,26 @@
|
|||||||
-include_lib("eqc/include/eqc.hrl").
|
-include_lib("eqc/include/eqc.hrl").
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
|
|
||||||
nonce_good() ->
|
%% Generator for binaries of a given size with different properties and fault injection:
|
||||||
Sz = enacl:box_nonce_size(),
|
g_binary(Sz) ->
|
||||||
binary(Sz).
|
fault(g_binary_bad(Sz), g_binary_good(Sz)).
|
||||||
|
|
||||||
nonce_bad() ->
|
g_binary_good(Sz) when Sz =< 32 -> binary(Sz);
|
||||||
Sz = enacl:box_nonce_size(),
|
g_binary_good(Sz) -> eqc_gen:largebinary(Sz).
|
||||||
oneof([return(a), nat(), ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)]).
|
|
||||||
|
|
||||||
nonce_valid(N) when is_binary(N) ->
|
g_binary_bad(Sz) ->
|
||||||
Sz = enacl:box_nonce_size(),
|
frequency([
|
||||||
|
{5, ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)},
|
||||||
|
{1, elements([a, b])},
|
||||||
|
{1, int()}
|
||||||
|
]).
|
||||||
|
|
||||||
|
v_binary(Sz, N) when is_binary(N) ->
|
||||||
byte_size(N) == Sz;
|
byte_size(N) == Sz;
|
||||||
nonce_valid(_) -> false.
|
v_binary(_, _) -> false.
|
||||||
|
|
||||||
nonce() ->
|
nonce() -> g_binary(enacl:box_nonce_size()).
|
||||||
fault(nonce_bad(), nonce_good()).
|
nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N).
|
||||||
|
|
||||||
keypair_good() ->
|
keypair_good() ->
|
||||||
#{ public := PK, secret := SK} = enacl:box_keypair(),
|
#{ public := PK, secret := SK} = enacl:box_keypair(),
|
||||||
@ -426,24 +431,13 @@ prop_onetime_auth_verify_correct() ->
|
|||||||
%% HASHING
|
%% HASHING
|
||||||
%% ---------------------------
|
%% ---------------------------
|
||||||
diff_pair(Sz) ->
|
diff_pair(Sz) ->
|
||||||
?SUCHTHAT({X, Y}, {binary(Sz), binary(Sz)},
|
?SUCHTHAT({X, Y}, {g_binary(Sz), g_binary(Sz)},
|
||||||
X /= Y).
|
X /= Y).
|
||||||
|
|
||||||
data_bad() ->
|
|
||||||
oneof([return(a), nat()]).
|
|
||||||
|
|
||||||
data_good(Sz) -> binary(Sz).
|
|
||||||
|
|
||||||
data(Sz) ->
|
|
||||||
fault(data_bad(), data_good(Sz)).
|
|
||||||
|
|
||||||
data_valid(B) when is_binary(B) -> true;
|
|
||||||
data_valid(_B) -> false.
|
|
||||||
|
|
||||||
prop_crypto_hash_eq() ->
|
prop_crypto_hash_eq() ->
|
||||||
?FORALL(Sz, oneof([1, 128, 1024, 1024*4]),
|
?FORALL(Sz, oneof([1, 128, 1024, 1024*4]),
|
||||||
?FORALL(X, data(Sz),
|
?FORALL(X, g_binary(Sz),
|
||||||
case data_valid(X) of
|
case is_binary(X) of
|
||||||
true -> equals(enacl:hash(X), enacl:hash(X));
|
true -> equals(enacl:hash(X), enacl:hash(X));
|
||||||
false ->
|
false ->
|
||||||
try
|
try
|
||||||
|
25
src/enacl_ext.erl
Normal file
25
src/enacl_ext.erl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
%%% @doc module enacl_ext implements various enacl extensions.
|
||||||
|
%%% <p>None of the extensions listed here are part of the official NaCl library.
|
||||||
|
%%% Things may be removed without further notice if it suddenly ends up being
|
||||||
|
%%% better to do something differently than the solution given here.
|
||||||
|
%%% </p>
|
||||||
|
-module(enacl_ext).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
scramble_block_16/2
|
||||||
|
]).
|
||||||
|
|
||||||
|
%% @doc scramble_block_16/2 scrambles (encrypt) a block under a given key
|
||||||
|
%% The rules are that the block is 16 bytes and the key is 32 bytes. The block
|
||||||
|
%% is scrambled by means of the (secret) key. This makes it impossible for an
|
||||||
|
%% attacker to understand the original input for the scrambling. The intention
|
||||||
|
%% of this method is to protect counters from leaking to the outside world, by
|
||||||
|
%% scrambling them before they leave the system.
|
||||||
|
%%
|
||||||
|
%% Scrambling is done by means of the TEA algorithm (Tiny Encryption Algorithm)
|
||||||
|
%% It has known weaknesses and should probably not be used long-term going
|
||||||
|
%% forward, but CurveCP currently uses it for nonce scrambling.
|
||||||
|
%% @end
|
||||||
|
-spec scramble_block_16(binary(), binary()) -> binary().
|
||||||
|
scramble_block_16(Block, Key) ->
|
||||||
|
enacl_nif:scramble_block_16(Block, Key).
|
@ -78,6 +78,11 @@
|
|||||||
randombytes_b/1
|
randombytes_b/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
%% Undocumented features :>
|
||||||
|
-export([
|
||||||
|
scramble_block_16/2
|
||||||
|
]).
|
||||||
|
|
||||||
-on_load(init/0).
|
-on_load(init/0).
|
||||||
|
|
||||||
init() ->
|
init() ->
|
||||||
@ -153,3 +158,4 @@ crypto_verify_32(_X, _Y) -> not_loaded().
|
|||||||
randombytes(_RequestedSize) -> not_loaded().
|
randombytes(_RequestedSize) -> not_loaded().
|
||||||
randombytes_b(_RequestedSize) -> not_loaded().
|
randombytes_b(_RequestedSize) -> not_loaded().
|
||||||
|
|
||||||
|
scramble_block_16(_Block, _Key) -> not_loaded().
|
||||||
|
Loading…
x
Reference in New Issue
Block a user