Loup Vaillant [Thu, 22 Mar 2018 20:47:13 +0000 (21:47 +0100)]
Corrected possible misalignment in the tests
Argon2i must have its work area aligned for uint64_t. I don't recall
any guarantee of alignment when allocating an array of uint8_t on the
stack. So we allocate on the heap instead.
Loup Vaillant [Thu, 22 Mar 2018 12:30:21 +0000 (13:30 +0100)]
Added a test vector for Argon2i
Libsodium's API doesn't let the user specify the `key` and `ad`
arguments. An implementation that flips them by mistake would still
pass the test vectors.
So I added a test vector from the reference implementation (hard coded,
to avoid dragging the whole reference implementation with us). With
that, we're sure `key` and `ad` are processed in the right order.
It wouldn't have affected security, but due diligence can't hurt.
Loup Vaillant [Tue, 6 Mar 2018 22:34:24 +0000 (23:34 +0100)]
More auditable code for Poly1305
The invariants in the comments have been updated, and a couple minor
errors of no consequence were corrected.
The final reduction code of crypto_poly1305_final() has been modified to
facilitate audits and formal proofs. This was motivated by the
following semi-formal proof:
Loup Vaillant [Sun, 25 Feb 2018 20:00:46 +0000 (21:00 +0100)]
More readable and more flexible loading code
The loading code for Chacha20, Poly1305, Blake2b, and SHA-512 was a bit
ad-hoc. This made it a bit impenetrable, as well as error prone.
Chacha20 in particular was harder than it should be to adapt to faster
implementation that proceed by several blocks at a time. So was
Poly1305, I think.
The loading code has been modified to conform to the following pattern:
1. Align ourselves with block boundaries
2. Process the message block by block
3. remaining bytes
- The last section just calls general purpose update code. It's the only
one that's mandatory.
- The first section calls the same general purpose update code, with
just enough input to reach the next block boundary. It must be
present whenever the second section is.
- The second section does optimised block-by-block update. It needs the
first section to ensure alignment.
Each section but the last updates the input pointers and lengths,
allowing later sections may assume they were the first.
Tests were performed with sections 1 2 3, 1 3, and 3 alone. They all
yield the same, correct results. We could write an equivalence proof,
but the property-based tests were designed to catch mistakes in the
loading code in the first place. Maybe not worth the trouble.
Loup Vaillant [Mon, 12 Feb 2018 20:25:59 +0000 (21:25 +0100)]
Renamed crypto_aead_(un)lock to crypto_(un)lock_aead
Related to #89
This is better for consistency (now authenticated encryption always
begins by "crypto_lock" or "crypto_unlock"), and has the added benefit
of warning developers of the major breaking changes triggered by IETF
padding.
Loup Vaillant [Sat, 10 Feb 2018 19:16:22 +0000 (20:16 +0100)]
Removed divison operations
This has no effect on most platform with most modern compiler, and makes
the code slightly less readable to boot.
But.
Some compilers may fail to transform divisions by a power of two into
the relevant shift or mask. Moreover, some platforms sport a variable
time division operation.
In the name of safety against timing attacks, those operation have been
removed explicitly. Only one remains, in Argon2i, but its operands are
not secret.
Loup Vaillant [Sat, 10 Feb 2018 18:25:28 +0000 (19:25 +0100)]
Changed authenticated encryptio to match RFC 7539
Closes #87
This is a breaking change. For data in transit, update everyone at
once. For data at rest, decrypt then re-encrypt everything. Sorry
about that. I should have thought this through earlier.
The main reason for this change is speed. While Monocypher doesn't aim
to be as fast as possible itself, it *does* aim to allow upgrades. By
ensuring that processing is aligned to block boundaries, RFC 7539
simplifies the implementation of fast algorithms.
This change brings the following benefits:
- Users who need the best speed possible ever can upgrade.
- The length of the additional data is now authenticated, closing a
potential minor vulnerability.
- We can use Libsodium's crypto_aead_xchacha20poly1305_ietf_encrypt to
generate test vectors.
---
The monolithic interface stays the same. Function names, types, and
buffer sizes, are identical. Just recompile your programs to upgrade.
The incremental interface has been changed to be more orthogonal:
`crypto_lock_encrypt()` and `crypto_lock_auth()` have been removed.
There shall be one true AEAD construction, users don't need those
building blocks. Users who *really* need another AEAD construction can
write it themselves with the low-level primitives.
`crypto_lock_aead_auth()` and `crypto_unlock_aead_auth()` have been
renamed `crypto_lock_auth_ad()` and `crypto_unlock_auth_ad()`
respectively. "aead" was a misnomer, those functions only authenticate
additional data.
`crypto_lock_auth_message()` and `crypto_unlock_auth_message()` have
been added. They authenticate the cipher text. Their main use is
performing a separate authentication pass (usefull when users expect a
high corruption rate).
Loup Vaillant [Fri, 9 Feb 2018 20:58:27 +0000 (21:58 +0100)]
Less provocative introductory paragraph
Some people interpret the previous wording to mean that Monocypher
already eats Libsodium's lunch, which is obviously false. Status
slap-down ensues, and I have to explain the difference between "means to"
and "does".
This also hints more clearly at the scope of Monocypher: do no more than
TweetNacl (except for password key derivation), stay small and portable
without sacrificing too much speed. (That scope may need to be clearly
stated somewhere.)
Loup Vaillant [Wed, 7 Feb 2018 22:55:51 +0000 (23:55 +0100)]
Better wording for Poly1305 security considerations
Fixes #84. I hope.
Some users *will* use Poly1305 for who knows what nefarious purpose I
haven't anticipated. This is why we expose low-level primitives in the
first place.
This may sound bikeshed-y, but Poly1305 is quite exacting. Not as bad
as AES-GCM from what I've heard, but close. So the manual must be
precise and unambiguous.
Loup Vaillant [Sat, 3 Feb 2018 22:22:25 +0000 (23:22 +0100)]
More accurate speed benchmark
Used smaller buffers to minimise the impact of cache misses in the
benchmark. Chosen a size that makes Libsodium and Monocypher look best.
(There is a trade-off between start up time and throughput.)
This should highlight the algorithmic differences better. Still, the
memory access patterns are very clean, computation tends to dominate.
Ultimately, this makes little difference.
Loup Vaillant [Sun, 28 Jan 2018 23:31:00 +0000 (00:31 +0100)]
Fixed erroneous crypto_wipe() calls
And used convenience macros in the process, depending on whether we wipe
a buffer or a structure (generally a context). The redundancy led to
some errors, which should be fixed by now.
Loup Vaillant [Sun, 14 Jan 2018 12:42:38 +0000 (13:42 +0100)]
More concise Chacha20
Partially reverts the optimisation from d1be682. Hoisting the test out
of the loop entirely was overkill. One level is sufficient, pushing it
any further has negligible impact.
Loup Vaillant [Thu, 11 Jan 2018 17:35:07 +0000 (18:35 +0100)]
Optimised chacha20 loading & unloading
Testing inside the loop caused a noticeable slow down. Now the whole
thing looks kinda like a copy-pasta job, but the alternative was a less
readable data flow anyway.
Loup Vaillant [Thu, 11 Jan 2018 16:55:37 +0000 (17:55 +0100)]
Adds high-level aliases to some low-level primitives
Some low-level primitives are actually suitable as high-level functions.
However, using them as such makes naming inconsistent and confusing.
Proper aliases have been added to make user code more consistent.
Macros (#define) have been used instead of function pointers to avoid
various compilation problems.
Loup Vaillant [Sat, 6 Jan 2018 12:46:05 +0000 (13:46 +0100)]
removed useless check
If the public key is not in the curve, the verification will simply
fail. There is little point verifying the validity of a signing public
key, since you have to trust its origin in the first place.