From 7f857115bbd0d38ea78fd84adc5bdd30a550a7ee Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Tue, 21 Jan 2020 14:16:24 +0100 Subject: [PATCH] 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. --- CHANGELOG.md | 24 ++++++++++++++-------- c_src/aead.c | 24 +++++++++++----------- c_src/aead.h | 24 +++++++++++----------- c_src/enacl_nif.c | 24 +++++++++++----------- src/enacl.erl | 48 ++++++++++++++++++++++---------------------- src/enacl_nif.erl | 24 +++++++++++----------- test/enacl_SUITE.erl | 12 +++++------ 7 files changed, 94 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c192c35..9dbff29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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] diff --git a/c_src/aead.c b/c_src/aead.c index 4339c99..24a71f1 100644 --- a/c_src/aead.c +++ b/c_src/aead.c @@ -9,33 +9,33 @@ * AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +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, - ERL_NIF_TERM const argv[]) { +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, - ERL_NIF_TERM const argv[]) { +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, - ERL_NIF_TERM const argv[]) { +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,8 +80,8 @@ done: } ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]) { +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; diff --git a/c_src/aead.h b/c_src/aead.h index 5188c9f..948cc3d 100644 --- a/c_src/aead.h +++ b/c_src/aead.h @@ -5,23 +5,23 @@ /* AEAD ChaCha20 Poly1305 */ ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_KEYBYTES(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +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, - ERL_NIF_TERM const argv[]); +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, - ERL_NIF_TERM const argv[]); +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, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX( + 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[]); +enacl_crypto_aead_chacha20poly1305_ietf_encrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); ERL_NIF_TERM -enacl_crypto_aead_chacha20poly1305_decrypt(ErlNifEnv *env, int argc, - ERL_NIF_TERM const argv[]); +enacl_crypto_aead_chacha20poly1305_ietf_decrypt(ErlNifEnv *env, int argc, + ERL_NIF_TERM const argv[]); /* AEAD XChaCha20 Poly1305 */ ERL_NIF_TERM diff --git a/c_src/enacl_nif.c b/c_src/enacl_nif.c index afa56da..cdf6e7d 100644 --- a/c_src/enacl_nif.c +++ b/c_src/enacl_nif.c @@ -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}, diff --git a/src/enacl.erl b/src/enacl.erl index 2a3d032..d00256a 100644 --- a/src/enacl.erl +++ b/src/enacl.erl @@ -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 %% ---------------------- diff --git a/src/enacl_nif.erl b/src/enacl_nif.erl index dfa7b97..97816a0 100644 --- a/src/enacl_nif.erl +++ b/src/enacl_nif.erl @@ -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). diff --git a/test/enacl_SUITE.erl b/test/enacl_SUITE.erl index b752bba..5798b7f 100644 --- a/test/enacl_SUITE.erl +++ b/test/enacl_SUITE.erl @@ -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) ->