Add aead IETF constructions

Since the chacha20poly1305 constructions were the IETF variants,
we renamed those so they follow the official library better. While
here, we also fixed the argument order of the files.
This commit is contained in:
Jesper Louis Andersen 2020-01-21 14:16:24 +01:00
parent bdb4719f6d
commit 7f857115bb
7 changed files with 94 additions and 86 deletions

View File

@ -10,17 +10,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
Over time, a number of bad things have snuck themselves into these bindings. This
is a list of changes which are planned for a 1.0 release.
- The argument order in some of the AEAD constructions doesn't follow those of
sodium. They should.
- The AEAD_chacha20_poly1305 construction does the nonce wrong. It assumes a 64bit
integer, though the real underlying construction accepts 12 bytes. The key isn't
generated like this. The AEAD_xchacha20_poly1305 construction does it correctly.
- Plug some subtle allocation leaks in the kx code.
- Plug some subtle memory leaks in the public API.
## [Unreleased]
### Compatibility
- If you used `aead_chacha20poly1305_*` functions, please read through the changelog
carefully as we have made changes to these functions. TL;DR: look for
`aead_chacha20poly1305_ietf_*` but note it is *not* just a simple substitution
into your code.
### Removed
- The functions of the form `aead_chacha20poly1305_*` were removed. They implement
the IETF variant, and the argument order for them were wrong. Also, they used
severely limited nonce values, which is somewhat dangerous. The `..._NONCEBYTES`
name was changed to the consistent `..._NPUBBYTES`.
### Added
- Added `aead_chacha20poly1305_ietf_*` variants.
- Implement multipart signature support, by Garry Hill.
- Implement enacl:crypto_sign_seed_keypair/1, by Ole Andre Birkedal.
- Implement enacl:crypto_sign_ed25519_sk_to_pk/1, by an anonymous contribution.
@ -58,8 +65,9 @@ is a list of changes which are planned for a 1.0 release.
### Fixes
- Fix a resource leak in generichash/sign init/update/final.
- Clang static analysis warnings (Thomas Arts)
- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review)
- Clang static analysis warnings (Thomas Arts).
- Replace a constant 31 with a computation from libsodium (Thomas Arts, from a security review).
- Some subtle memory leaks in the error path for kx operations were plugged.
## [0.17.2]

View File

@ -9,32 +9,32 @@
* AEAD ChaCha20 Poly1305
*/
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
}
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
}
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
return enif_make_int64(env, crypto_aead_chacha20poly1305_ietf_ABYTES);
}
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX(
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]) {
return enif_make_int64(env,
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
}
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ERL_NIF_TERM ret;
ErlNifBinary key, nonce, ad, message, ciphertext;
@ -80,7 +80,7 @@ done:
}
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ERL_NIF_TERM ret;
ErlNifBinary key, nonce, ad, message, ciphertext;

View File

@ -5,22 +5,22 @@
/* AEAD ChaCha20 Poly1305 */
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_NPUBBYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_ABYTES(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_ABYTES(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX(
ErlNifEnv *env, int argc, ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_encrypt(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
ERL_NIF_TERM
enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc,
enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
/* AEAD XChaCha20 Poly1305 */

View File

@ -405,20 +405,20 @@ static ErlNifFunc nif_funcs[] = {
{"scramble_block_16", 2, enif_scramble_block_16},
{"crypto_aead_chacha20poly1305_KEYBYTES", 0,
enacl_crypto_aead_chacha20poly1305_KEYBYTES},
{"crypto_aead_chacha20poly1305_NPUBBYTES", 0,
enacl_crypto_aead_chacha20poly1305_NPUBBYTES},
{"crypto_aead_chacha20poly1305_ABYTES", 0,
enacl_crypto_aead_chacha20poly1305_ABYTES},
{"crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX", 0,
enacl_crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX},
{"crypto_aead_chacha20poly1305_ietf_KEYBYTES", 0,
enacl_crypto_aead_chacha20poly1305_ietf_KEYBYTES},
{"crypto_aead_chacha20poly1305_ietf_NPUBBYTES", 0,
enacl_crypto_aead_chacha20poly1305_ietf_NPUBBYTES},
{"crypto_aead_chacha20poly1305_ietf_ABYTES", 0,
enacl_crypto_aead_chacha20poly1305_ietf_ABYTES},
{"crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", 0,
enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX},
erl_nif_dirty_job_cpu_bound_macro(
"crypto_aead_chacha20poly1305_encrypt", 4,
enacl_crypto_aead_chacha20poly1305_encrypt),
"crypto_aead_chacha20poly1305_ietf_encrypt", 4,
enacl_crypto_aead_chacha20poly1305_ietf_encrypt),
erl_nif_dirty_job_cpu_bound_macro(
"crypto_aead_chacha20poly1305_decrypt", 4,
enacl_crypto_aead_chacha20poly1305_decrypt),
"crypto_aead_chacha20poly1305_ietf_decrypt", 4,
enacl_crypto_aead_chacha20poly1305_ietf_decrypt),
{"crypto_aead_xchacha20poly1305_KEYBYTES", 0,
enacl_crypto_aead_xchacha20poly1305_KEYBYTES},

View File

@ -66,12 +66,12 @@
stream_chacha20_xor/3,
%% EQC
aead_chacha20poly1305_encrypt/4,
aead_chacha20poly1305_decrypt/4,
aead_chacha20poly1305_KEYBYTES/0,
aead_chacha20poly1305_NPUBBYTES/0,
aead_chacha20poly1305_ABYTES/0,
aead_chacha20poly1305_MESSAGEBYTES_MAX/0,
aead_chacha20poly1305_ietf_encrypt/4,
aead_chacha20poly1305_ietf_decrypt/4,
aead_chacha20poly1305_ietf_KEYBYTES/0,
aead_chacha20poly1305_ietf_NPUBBYTES/0,
aead_chacha20poly1305_ietf_ABYTES/0,
aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0,
%% No Tests!
aead_xchacha20poly1305_encrypt/4,
@ -1169,54 +1169,54 @@ kx_secret_key_size() ->
%% `AD' using `Key' and `Nonce'. Returns the encrypted message followed by
%% `aead_chacha20poly1305_ABYTES/0' bytes of MAC.
%% @end
-spec aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()}
-spec aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) -> binary() | {error, term()}
when Key :: binary(),
Nonce :: binary(),
AD :: binary(),
Msg :: binary().
aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key) ->
enacl_nif:crypto_aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key).
aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key) ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key).
%% @doc aead_chacha20poly1305_decrypt/4 decrypts ciphertext `CT' with additional
%% data `AD' using `Key' and `Nonce'. Note: `CipherText' should contain
%% `aead_chacha20poly1305_ABYTES/0' bytes that is the MAC. Returns the decrypted
%% message.
%% @end
-spec aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()}
-spec aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) -> binary() | {error, term()}
when Key :: binary(),
Nonce :: binary(),
AD :: binary(),
CT :: binary().
aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key) ->
enacl_nif:crypto_aead_chacha20poly1305_decrypt(CT, AD, Nonce, Key).
aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key) ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_decrypt(CT, AD, Nonce, Key).
%% @doc aead_chacha20poly1305_KEYBYTES/0 returns the number of bytes
%% of the key used in AEAD ChaCha20 Poly1305 encryption/decryption.
%% @end
-spec aead_chacha20poly1305_KEYBYTES() -> pos_integer().
aead_chacha20poly1305_KEYBYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_KEYBYTES().
-spec aead_chacha20poly1305_ietf_KEYBYTES() -> pos_integer().
aead_chacha20poly1305_ietf_KEYBYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_KEYBYTES().
%% @doc aead_chacha20poly1305_NPUBBYTES/0 returns the number of bytes
%% of the Nonce in AEAD ChaCha20 Poly1305 encryption/decryption.
%% @end
-spec aead_chacha20poly1305_NPUBBYTES() -> pos_integer().
aead_chacha20poly1305_NPUBBYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_NPUBBYTES().
-spec aead_chacha20poly1305_ietf_NPUBBYTES() -> pos_integer().
aead_chacha20poly1305_ietf_NPUBBYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_NPUBBYTES().
%% @doc aead_chacha20poly1305_ABYTES/0 returns the number of bytes
%% of the MAC in AEAD ChaCha20 Poly1305 encryption/decryption.
%% @end
-spec aead_chacha20poly1305_ABYTES() -> pos_integer().
aead_chacha20poly1305_ABYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_ABYTES().
-spec aead_chacha20poly1305_ietf_ABYTES() -> pos_integer().
aead_chacha20poly1305_ietf_ABYTES() ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_ABYTES().
%% @doc aead_chacha20poly1305_MESSAGEBYTES_MAX/0 returns the max number of bytes
%% allowed in a message in AEAD ChaCha20 Poly1305 encryption/decryption.
%% @end
-spec aead_chacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer().
aead_chacha20poly1305_MESSAGEBYTES_MAX() ->
enacl_nif:crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX().
-spec aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> pos_integer().
aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() ->
enacl_nif:crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX().
%% AEAD XChaCha20 Poly1305
%% ----------------------

View File

@ -74,12 +74,12 @@
crypto_stream_xor/3,
crypto_stream_xor_b/3,
crypto_aead_chacha20poly1305_encrypt/4,
crypto_aead_chacha20poly1305_decrypt/4,
crypto_aead_chacha20poly1305_KEYBYTES/0,
crypto_aead_chacha20poly1305_NPUBBYTES/0,
crypto_aead_chacha20poly1305_ABYTES/0,
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX/0,
crypto_aead_chacha20poly1305_ietf_encrypt/4,
crypto_aead_chacha20poly1305_ietf_decrypt/4,
crypto_aead_chacha20poly1305_ietf_KEYBYTES/0,
crypto_aead_chacha20poly1305_ietf_NPUBBYTES/0,
crypto_aead_chacha20poly1305_ietf_ABYTES/0,
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX/0,
crypto_aead_xchacha20poly1305_encrypt/4,
crypto_aead_xchacha20poly1305_decrypt/4,
@ -272,12 +272,12 @@ crypto_stream_b(_Bytes, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_stream_xor(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_stream_xor_b(_M, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_NPUBBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_NPUBBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_ABYTES() -> erlang:nif_error(nif_not_loaded).
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
crypto_aead_xchacha20poly1305_encrypt(_Message, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_aead_xchacha20poly1305_decrypt(_CipherText, _AD, _Nonce, _Key) -> erlang:nif_error(nif_not_loaded).

View File

@ -41,7 +41,7 @@ groups() ->
[generichash_basic_pos,
generichash_chunked,
aead_xchacha20poly1305,
aead_chacha20poly1305,
aead_chacha20poly1305_ietf,
pwhash,
sign,
kx]},
@ -102,16 +102,16 @@ aead_xchacha20poly1305(_Config) ->
Msg = enacl:aead_xchacha20poly1305_decrypt(Key, Nonce, AD, CipherText),
ok.
aead_chacha20poly1305(_Config) ->
NonceLen = enacl:aead_chacha20poly1305_NPUBBYTES(),
KLen = enacl:aead_chacha20poly1305_KEYBYTES(),
aead_chacha20poly1305_ietf(_Config) ->
NonceLen = enacl:aead_chacha20poly1305_ietf_NPUBBYTES(),
KLen = enacl:aead_chacha20poly1305_ietf_KEYBYTES(),
Key = binary:copy(<<"K">>, KLen),
Msg = <<"test">>,
AD = <<1,2,3,4,5,6>>,
Nonce = binary:copy(<<"N">>, NonceLen),
CipherText = enacl:aead_chacha20poly1305_encrypt(Msg, AD, Nonce, Key),
Msg = enacl:aead_chacha20poly1305_decrypt(CipherText, AD, Nonce, Key),
CipherText = enacl:aead_chacha20poly1305_ietf_encrypt(Msg, AD, Nonce, Key),
Msg = enacl:aead_chacha20poly1305_ietf_decrypt(CipherText, AD, Nonce, Key),
ok.
pwhash(_Config) ->