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) ->