The API for pwhash_str returns a cstring in the output buffer. These
are null terminated. However, we return the full buffer as a binary
back to Erlang. This means that we have a buffer with 0'es in the end.
The tests take this buffer and passes it back in as is. Hence all the
tests pass. However, it is conceivable that if we write said buffer to
disk somewhere, we are not going to write those 0's out.
When we then load the ASCII-armored Argon2 string into memory again,
it is not 0-terminated as a cstring should be, and this produces
errors all over the place.
The fix is twofold:
* Return the full buffer to Erlang, but use binary:split/2 to create a
subbinary with the relevant part.
* Add a 0 in the end of ASCII Argon2 string before passing it to
libsodium
Since we are looking at pwhashing, and Argon2, we expect the
computational problem to be memory bound. Thus, spending a bit more
work in memory is not going to have any considerable impact on the
speed of this system.
These variables are being initialized via calls to `enif_get_uint`,
so it's safer to declare them as unsigned int's rather than size_t's.
Their being used in calls to `enif_alloc_binary`, which takes a size_t
as its size.
However, the resulting ErlNifBinary keeps its size as an unsigned int,
so asking for a size that's an unsigned int should be safe.
This would be problematic in the case where sizeof(size_t) <
sizeof(unsigned), which would mean we're getting fewer bytes allocated
than expected.
Perhaps an explicit check for, for example, `hashSize > MAX_SIZE` would
be good here?
Investigation shows erratic behaviour of the CSPRNG. It may block at times
because it needs to go to the kernel and obtain more random information in
the system. Once this happens, you are blocked for quite a long time, but
we don't generally know when this happens. So just execute these directly
on the dirty scheduler.
* Introduce enacl:verify/0 to verify the integrity of the library.
* Always run keypair functions on the dirty schedulers.
* Do not call NIFs when creating zerobytes. Avoid constructing new binary data, but reuse a constant.
* The box/box_open and box_seal/box_seal_open API is so expensive to call there is little overhead in
running it on the DS always.
* Call the functions `box_seal` and `box_seal_open` to match the libsodium names in module `enacl`.
* Fix a bug in the C NIF: We should fail if the input is `<` SEALBYTES but not on `<=` SEALBYTES. The latter made it impossible to encode empty messages.
* Add variants which run directly on the interpreter scheduler for small messages.
Also:
* Provide full EQC functions for the testing purposes. This generated around 13000 random test cases in a 5 minute run, all passing.# Please enter the commit message for your changes. Lines starting
Provide non-dirty-scheduler variants for small strings, accurately bump
reductions for these strings.
While here, provide EQC test cases for the two functions.
If we write
EXP != 0
and EXP is a very large term, it is hard to see what it gets checked against, so we rewrite it as
0 != EXP
so we instanly see what we check against. While here, teset against 0 != crypto_box_afternm(…)
* 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.