Merge pull request #44 from spscream/master

Add crypto_secretstream_* functions.
This commit is contained in:
Jesper Louis Andersen 2020-03-07 11:31:30 +01:00 committed by GitHub
commit 55b3670fe7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 788 additions and 2 deletions

View File

@ -14,6 +14,7 @@
#include "randombytes.h"
#include "secret.h"
#include "sign.h"
#include "secretstream.h"
#ifdef ERL_NIF_DIRTY_JOB_CPU_BOUND
#define erl_nif_dirty_job_cpu_bound_macro(a, b, c) \
@ -35,6 +36,10 @@ static int enacl_crypto_load(ErlNifEnv *env, void **priv_data,
return -1;
}
if (!enacl_init_secretstream_ctx(env)) {
return -1;
}
return sodium_init();
}
@ -372,8 +377,24 @@ static ErlNifFunc nif_funcs[] = {
erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_update", 2,
enacl_crypto_generichash_update),
erl_nif_dirty_job_cpu_bound_macro("crypto_generichash_final", 1,
enacl_crypto_generichash_final)
enacl_crypto_generichash_final),
{"crypto_secretstream_xchacha20poly1305_ABYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_ABYTES},
{"crypto_secretstream_xchacha20poly1305_HEADERBYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES},
{"crypto_secretstream_xchacha20poly1305_KEYBYTES", 0, enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES},
{"crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", 0, enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX},
{"crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE},
{"crypto_secretstream_xchacha20poly1305_TAG_PUSH", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH},
{"crypto_secretstream_xchacha20poly1305_TAG_REKEY", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY},
{"crypto_secretstream_xchacha20poly1305_TAG_FINAL", 0, enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL},
{"crypto_secretstream_xchacha20poly1305_keygen", 0, enacl_crypto_secretstream_xchacha20poly1305_keygen},
{"crypto_secretstream_xchacha20poly1305_init_push", 1, enacl_crypto_secretstream_xchacha20poly1305_init_push},
{"crypto_secretstream_xchacha20poly1305_init_pull", 2, enacl_crypto_secretstream_xchacha20poly1305_init_pull},
{"crypto_secretstream_xchacha20poly1305_rekey", 1, enacl_crypto_secretstream_xchacha20poly1305_rekey},
erl_nif_dirty_job_cpu_bound_macro("crypto_secretstream_xchacha20poly1305_push", 4,
enacl_crypto_secretstream_xchacha20poly1305_push),
erl_nif_dirty_job_cpu_bound_macro("crypto_secretstream_xchacha20poly1305_pull", 3,
enacl_crypto_secretstream_xchacha20poly1305_pull)
};
ERL_NIF_INIT(enacl_nif, nif_funcs, enacl_crypto_load, NULL, NULL, NULL);

461
c_src/secretstream.c Normal file
View File

@ -0,0 +1,461 @@
#include <sodium.h>
#include <erl_nif.h>
#include "enacl.h"
#include "secretstream.h"
typedef struct enacl_secretstream_ctx {
ErlNifMutex *mtx;
crypto_secretstream_xchacha20poly1305_state *state; // The underlying secretstream state
int alive; // Is the context still valid for updates/finalization
} enacl_secretstream_ctx;
ErlNifResourceType *enacl_secretstream_ctx_rtype = NULL;
static void enacl_secretstream_ctx_dtor(ErlNifEnv *env,
enacl_secretstream_ctx *);
int enacl_init_secretstream_ctx(ErlNifEnv *env) {
enacl_secretstream_ctx_rtype =
enif_open_resource_type(env, NULL, "enacl_secretstream_context",
(ErlNifResourceDtor *)enacl_secretstream_ctx_dtor,
ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER, NULL);
if (enacl_secretstream_ctx_rtype == NULL)
return 0;
return 1;
}
static void enacl_secretstream_ctx_dtor(ErlNifEnv *env,
enacl_secretstream_ctx *obj) {
if (!obj->alive) {
return;
}
if (obj->state)
sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes());
enif_free(obj->state);
if (obj->mtx != NULL)
enif_mutex_destroy(obj->mtx);
return;
}
/*
* Secretstream
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_ABYTES);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_KEYBYTES);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_PUSH);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_REKEY);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
return enif_make_int64(env, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
}
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ErlNifBinary key;
if (argc != 0) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_KEYBYTES, &key)) {
return enacl_internal_error(env);
}
crypto_secretstream_xchacha20poly1305_keygen(key.data);
return enif_make_binary(env, &key);
}
/*
int crypto_secretstream_xchacha20poly1305_init_push
(crypto_secretstream_xchacha20poly1305_state *state,
unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
) {
ERL_NIF_TERM ret;
ErlNifBinary key, header;
enacl_secretstream_ctx *obj = NULL;
if ((argc != 1) || (!enif_inspect_binary(env, argv[0], &key))) {
goto bad_arg;
}
if (key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) {
goto bad_arg;
}
if (!enif_alloc_binary(crypto_secretstream_xchacha20poly1305_HEADERBYTES, &header)) {
ret = enacl_internal_error(env);
goto done;
}
if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype,
sizeof(enacl_secretstream_ctx))) == NULL) {
ret = enacl_internal_error(env);
goto release_header;
}
obj->alive = 0;
obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes());
if (obj->state == NULL) {
goto release;
}
obj->alive = 1;
if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) {
goto free;
}
crypto_secretstream_xchacha20poly1305_init_push(obj->state, header.data, key.data);
ret = enif_make_tuple2(env,
enif_make_binary(env, &header),
enif_make_resource(env, obj)
);
goto release;
bad_arg:
return enif_make_badarg(env);
free:
if (obj->alive)
if (obj->state != NULL) {
sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes());
enif_free(obj->state);
obj->state = NULL;
}
release:
// This also frees the mutex via the destructor
enif_release_resource(obj);
release_header:
enif_release_binary(&header);
done:
return ret;
}
/*
crypto_secretstream_xchacha20poly1305_init_pull
(crypto_secretstream_xchacha20poly1305_state *state,
const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
) {
ERL_NIF_TERM ret;
ErlNifBinary header, key;
enacl_secretstream_ctx *obj = NULL;
if (argc != 2) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[0], &header)) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[1], &key)) {
goto bad_arg;
}
if ((key.size != crypto_secretstream_xchacha20poly1305_KEYBYTES) ||
(header.size != crypto_secretstream_xchacha20poly1305_HEADERBYTES))
{
goto bad_arg;
}
if((obj = enif_alloc_resource(enacl_secretstream_ctx_rtype,
sizeof(enacl_secretstream_ctx))) == NULL) {
ret = enacl_internal_error(env);
goto done;
}
obj->alive = 0;
obj->state = enif_alloc(crypto_secretstream_xchacha20poly1305_statebytes());
if (obj->state == NULL) {
goto release;
}
obj->alive = 1;
if ((obj->mtx = enif_mutex_create("enacl.secretstream")) == NULL) {
goto free;
}
crypto_secretstream_xchacha20poly1305_init_pull(obj->state, header.data, key.data);
ret = enif_make_resource(env, obj);
goto release;
bad_arg:
return enif_make_badarg(env);
free:
if (obj->alive)
if (obj->state != NULL) {
sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes());
enif_free(obj->state);
obj->state = NULL;
}
release:
// This also frees the mutex via the destructor
enif_release_resource(obj);
done:
return ret;
}
/*
void
crypto_secretstream_xchacha20poly1305_rekey
(crypto_secretstream_xchacha20poly1305_state *state)
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
) {
ERL_NIF_TERM ret;
enacl_secretstream_ctx *obj = NULL;
if (argc != 1) {
goto bad_arg;
}
if(!enif_get_resource(env, argv[0],
(ErlNifResourceType *) enacl_secretstream_ctx_rtype,
(void **)&obj)) {
goto bad_arg;
}
enif_mutex_lock(obj->mtx);
if (!obj->alive) {
goto err;
}
crypto_secretstream_xchacha20poly1305_rekey(obj->state);
ret = enif_make_atom(env, ATOM_OK);
goto done;
bad_arg:
return enif_make_badarg(env);
err:
ret = enacl_error_finalized(env);
done:
enif_mutex_unlock(obj->mtx);
return ret;
}
/*
int
crypto_secretstream_xchacha20poly1305_push
(crypto_secretstream_xchacha20poly1305_state *state,
unsigned char *out, unsigned long long *outlen_p,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen, unsigned char tag)
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
) {
ERL_NIF_TERM ret;
ErlNifBinary m, ad, out;
ErlNifUInt64 tag;
enacl_secretstream_ctx *obj = NULL;
if (argc != 4) {
goto bad_arg;
}
if(!enif_get_resource(env, argv[0],
(ErlNifResourceType *) enacl_secretstream_ctx_rtype,
(void **)&obj)) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[1], &m)) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[2], &ad)) {
goto bad_arg;
}
if(!enif_get_uint64(env, argv[3], &tag)) {
goto bad_arg;
}
if (!enif_alloc_binary(m.size + crypto_secretstream_xchacha20poly1305_ABYTES, &out)) {
return enacl_internal_error(env);
}
enif_mutex_lock(obj->mtx);
if (!obj->alive) {
goto err;
}
crypto_secretstream_xchacha20poly1305_push(obj->state, out.data, NULL, m.data, m.size, ad.data, ad.size, tag);
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
if(obj->state) {
obj->alive = 0;
sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes());
enif_free(obj->state);
obj->state = NULL;
}
}
ret = enif_make_binary(env, &out);
goto done;
bad_arg:
return enif_make_badarg(env);
err:
ret = enacl_error_finalized(env);
enif_release_binary(&out);
done:
enif_mutex_unlock(obj->mtx);
return ret;
}
/*
crypto_secretstream_xchacha20poly1305_pull
(crypto_secretstream_xchacha20poly1305_state *state,
unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
const unsigned char *in, unsigned long long inlen,
const unsigned char *ad, unsigned long long adlen)
*/
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
) {
ERL_NIF_TERM ret;
ErlNifBinary m, in, ad;
unsigned char tag;
enacl_secretstream_ctx *obj = NULL;
if (argc != 3) {
goto bad_arg;
}
if(!enif_get_resource(env, argv[0],
(ErlNifResourceType *) enacl_secretstream_ctx_rtype,
(void **)&obj)) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[1], &in)) {
goto bad_arg;
}
if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) {
goto bad_arg;
}
if(!enif_inspect_binary(env, argv[2], &ad)) {
goto bad_arg;
}
if(in.size < crypto_secretstream_xchacha20poly1305_ABYTES) {
goto bad_arg;
}
if (!enif_alloc_binary(in.size - crypto_secretstream_xchacha20poly1305_ABYTES, &m)) {
return enacl_internal_error(env);
}
enif_mutex_lock(obj->mtx);
if(!obj->alive) {
goto err;
}
if (0 != crypto_secretstream_xchacha20poly1305_pull(obj->state, m.data, NULL, &tag, in.data, in.size, ad.data, ad.size)) {
ret = enacl_error_tuple(env, "failed_verification");
goto release;
}
if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
if(obj->state) {
obj->alive = 0;
sodium_memzero(obj->state, crypto_secretstream_xchacha20poly1305_statebytes());
enif_free(obj->state);
obj->state = NULL;
}
}
ret = enif_make_tuple2(env,
enif_make_binary(env, &m),
enif_make_int64(env, tag)
);
goto done;
bad_arg:
return enif_make_badarg(env);
err:
ret = enacl_error_finalized(env);
release:
enif_release_binary(&m);
done:
enif_mutex_unlock(obj->mtx);
return ret;
}

78
c_src/secretstream.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef ENACL_SECRETSTREAM_H
#define ENACL_SECRETSTREAM_H
#include <erl_nif.h>
int enacl_init_secretstream_ctx(ErlNifEnv *env);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_ABYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_HEADERBYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_KEYBYTES(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_MESSAGE(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_PUSH(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_REKEY(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_TAG_FINAL(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_keygen(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_push(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_init_pull(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_rekey(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_push(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
ERL_NIF_TERM enacl_crypto_secretstream_xchacha20poly1305_pull(
ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]
);
#endif

View File

@ -174,6 +174,25 @@
kx_SESSIONKEYBYTES/0
]).
%% Secretstream operations.
-export([
%% No Tests!
secretstream_xchacha20poly1305_ABYTES/0,
secretstream_xchacha20poly1305_HEADERBYTES/0,
secretstream_xchacha20poly1305_KEYBYTES/0,
secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0,
secretstream_xchacha20poly1305_TAG_MESSAGE/0,
secretstream_xchacha20poly1305_TAG_PUSH/0,
secretstream_xchacha20poly1305_TAG_REKEY/0,
secretstream_xchacha20poly1305_TAG_FINAL/0,
secretstream_xchacha20poly1305_keygen/0,
secretstream_xchacha20poly1305_init_push/1,
secretstream_xchacha20poly1305_push/4,
secretstream_xchacha20poly1305_init_pull/2,
secretstream_xchacha20poly1305_pull/3,
secretstream_xchacha20poly1305_rekey/1
]).
%% Internal verification of the system
-export([verify/0]).
@ -224,6 +243,11 @@
-define(CRYPTO_GENERICHASH_KEYBYTES_MAX, 64).
-define(CRYPTO_GENERICHASH_KEYBYTES, 32).
-define(CRYPTO_SECRETSTREAM_TAG_MESSAGE, 0).
-define(CRYPTO_SECRETSTREAM_TAG_PUSH, 1).
-define(CRYPTO_SECRETSTREAM_TAG_REKEY, 2).
-define(CRYPTO_SECRETSTREAM_TAG_FINAL, 3).
%% Size limits
-define(MAX_32BIT_INT, 1 bsl 32).
@ -253,7 +277,11 @@ verify() ->
{crypto_generichash_BYTES_MAX, ?CRYPTO_GENERICHASH_BYTES_MAX},
{crypto_generichash_KEYBYTES, ?CRYPTO_GENERICHASH_KEYBYTES},
{crypto_generichash_KEYBYTES_MIN, ?CRYPTO_GENERICHASH_KEYBYTES_MIN},
{crypto_generichash_KEYBYTES_MAX, ?CRYPTO_GENERICHASH_KEYBYTES_MAX}
{crypto_generichash_KEYBYTES_MAX, ?CRYPTO_GENERICHASH_KEYBYTES_MAX},
{crypto_secretstream_xchacha20poly1305_TAG_MESSAGE, ?CRYPTO_SECRETSTREAM_TAG_MESSAGE},
{crypto_secretstream_xchacha20poly1305_TAG_PUSH, ?CRYPTO_SECRETSTREAM_TAG_PUSH},
{crypto_secretstream_xchacha20poly1305_TAG_REKEY, ?CRYPTO_SECRETSTREAM_TAG_REKEY},
{crypto_secretstream_xchacha20poly1305_TAG_FINAL, ?CRYPTO_SECRETSTREAM_TAG_FINAL}
],
run_verifiers(Verifiers).
@ -1246,7 +1274,172 @@ aead_xchacha20poly1305_ietf_ABYTES() ->
aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX() ->
enacl_nif:crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX().
%% Secretstream
%% ----------------------
%% @doc secretstream_xchacha20poly1305_ABYTES/0 returns the number of bytes
%% of the MAC used on secretstream encryption/decryption
%% @end
-spec secretstream_xchacha20poly1305_ABYTES() -> pos_integer().
secretstream_xchacha20poly1305_ABYTES() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_ABYTES().
%% @doc secretstream_xchacha20poly1305_HEADERBYTES/0 returns the number
%% of bytes for header used in secretstream encryption/decryption.
%% @end
-spec secretstream_xchacha20poly1305_HEADERBYTES() -> pos_integer().
secretstream_xchacha20poly1305_HEADERBYTES() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_HEADERBYTES().
%% @doc secretstream_xchacha20poly1305_KEYBYTES/0 returns the number
%% of bytes of the key used in secretstream encryption/decryption.
%% @end
-spec secretstream_xchacha20poly1305_KEYBYTES() -> pos_integer().
secretstream_xchacha20poly1305_KEYBYTES() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_KEYBYTES().
%% @doc secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0 returns the max
%% number of bytes allowed in a message in secretstream encryption/decryption.
%% @end
-spec secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> pos_integer().
secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX().
%% @doc secretstream_xchacha20poly1305_TAG_MESSAGE/0 returns integer value
%% of tag `message'. The most common tag, that doesn't add any information
%% about the nature of the message.
%% @end
-spec secretstream_xchacha20poly1305_TAG_MESSAGE() -> pos_integer().
secretstream_xchacha20poly1305_TAG_MESSAGE() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_MESSAGE().
%% @doc secretstream_xchacha20poly1305_TAG_PUSH/0 returns integer value
%% of tag `push'.
%%
%% This tag indicates that the message marks the end
%% of a set of messages, but not the end of the stream.
%%
%% For example, a huge JSON string sent as multiple chunks can use
%% this tag to indicate to the application that the string is complete
%% and that it can be decoded. But the stream itself is not closed,
%% and more data may follow.
%% @end
-spec secretstream_xchacha20poly1305_TAG_PUSH() -> pos_integer().
secretstream_xchacha20poly1305_TAG_PUSH() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_PUSH().
%% @doc secretstream_xchacha20poly1305_TAG_REKEY/0 returns integer value
%% of tag `rekey'. Indicates that next messages will derive new keys.
%% @end
-spec secretstream_xchacha20poly1305_TAG_REKEY() -> pos_integer().
secretstream_xchacha20poly1305_TAG_REKEY() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_REKEY().
%% @doc secretstream_xchacha20poly1305_TAG_FINAL/0 returns integer value
%% of tag `final'. Indicates that the message is the last message in
%% the secretstream.
%% @end
-spec secretstream_xchacha20poly1305_TAG_FINAL() -> pos_integer().
secretstream_xchacha20poly1305_TAG_FINAL() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_FINAL().
%% @doc secretstream_xchacha20poly1305_keygen/0 returns new random key
%% for secretsteam encryption.
%% @end
-spec secretstream_xchacha20poly1305_keygen() -> binary().
secretstream_xchacha20poly1305_keygen() ->
enacl_nif:crypto_secretstream_xchacha20poly1305_keygen().
%% @doc secretstream_xchacha20poly1305_init_push/1
%% initializes a secretstream encryption context using given `key'.
%% Returns `Header' and reference to encryption context.
%% @end
-spec secretstream_xchacha20poly1305_init_push(Key) -> {binary(), reference()}
when Key :: binary().
secretstream_xchacha20poly1305_init_push(Key) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_init_push(Key).
-type secretstream_xchacha20poly1305_tag() :: message | rekey | final | push | pos_integer().
%% @doc secretstream_xchacha20poly1305_push/4 returns encrypted chunk binary.
%% Updates a secretstream context referenced by `Ref' with `Message' data,
%% given `Tag' and additional data `AD'.
%% @end
-spec secretstream_xchacha20poly1305_push(Ref, Message, AD, Tag) -> binary()
when
Ref :: reference(),
Message :: binary(),
AD :: binary(),
Tag :: secretstream_xchacha20poly1305_tag().
secretstream_xchacha20poly1305_push(Ref, Message, AD, Tag) ->
TagValue = secretstream_xchacha20poly1305_tag_value(Tag),
enacl_nif:crypto_secretstream_xchacha20poly1305_push(Ref, Message, AD, TagValue).
%% @doc secretstream_xchacha20poly1305_init_pull/3
%% initializes a secretstream decryption context using `Header' and `Key'.
%% Returns reference to decryption context.
%% @end
-spec secretstream_xchacha20poly1305_init_pull(Header, Key) -> reference()
when
Header :: binary(),
Key :: binary().
secretstream_xchacha20poly1305_init_pull(Header, Key) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_init_pull(Header, Key).
%% @doc secretstream_xchacha20poly1305_pull/3 decrypts `CipherText'
%% with additional data `AD' in referenced decryption context `Ref'.
%% @end
-spec secretstream_xchacha20poly1305_pull(Ref, CipherText, AD) ->
{binary(), secretstream_xchacha20poly1305_tag()} | {error, failed_verification}
when
Ref :: reference(),
CipherText :: binary(),
AD :: binary().
secretstream_xchacha20poly1305_pull(Ref, CipherText, AD) ->
{Message, TagValue} = enacl_nif:crypto_secretstream_xchacha20poly1305_pull(Ref, CipherText, AD),
{Message, secretstream_xchacha20poly1305_tag(TagValue)}.
%% @doc secretstream_xchacha20poly1305_rekey/1 updates encryption/decryption context state.
%% This doesn't add any information about key update to stream.
%% If this function is used to create an encrypted stream,
%% the decryption process must call that function at the exact same stream location.
%% @end
-spec secretstream_xchacha20poly1305_rekey(Ref) -> ok
when Ref :: reference().
secretstream_xchacha20poly1305_rekey(Ref) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_rekey(Ref).
%% @doc secretstream_xchacha20poly1305_tag_value/1 returns integer value of tag.
%% @end
-spec secretstream_xchacha20poly1305_tag_value(TagName) -> pos_integer()
when TagName :: secretstream_xchacha20poly1305_tag().
secretstream_xchacha20poly1305_tag_value(message) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_MESSAGE();
secretstream_xchacha20poly1305_tag_value(rekey) ->
enacl_nif:crypto_secretstream_xcacha20poly1305_TAG_REKEY();
secretstream_xchacha20poly1305_tag_value(push) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_PUSH();
secretstream_xchacha20poly1305_tag_value(final) ->
enacl_nif:crypto_secretstream_xchacha20poly1305_TAG_FINAL();
secretstream_xchacha20poly1305_tag_value(Other) ->
Other.
%% @doc secretstream_xchacha20poly1305_tag/1 returns tag name
%% @end
-spec secretstream_xchacha20poly1305_tag(TagValue) -> secretstream_xchacha20poly1305_tag()
when TagValue :: pos_integer().
secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_MESSAGE) ->
message;
secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_PUSH) ->
push;
secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_REKEY) ->
rekey;
secretstream_xchacha20poly1305_tag(?CRYPTO_SECRETSTREAM_TAG_FINAL) ->
final;
secretstream_xchacha20poly1305_tag(Other) ->
Other.
%% Obtaining random bytes
%% ----------------------
%% @doc randombytes/1 produces a stream of random bytes of the given size
%%

View File

@ -166,6 +166,24 @@
crypto_generichash_final/1
]).
%% Secretstream
-export([
crypto_secretstream_xchacha20poly1305_ABYTES/0,
crypto_secretstream_xchacha20poly1305_HEADERBYTES/0,
crypto_secretstream_xchacha20poly1305_KEYBYTES/0,
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX/0,
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE/0,
crypto_secretstream_xchacha20poly1305_TAG_PUSH/0,
crypto_secretstream_xchacha20poly1305_TAG_REKEY/0,
crypto_secretstream_xchacha20poly1305_TAG_FINAL/0,
crypto_secretstream_xchacha20poly1305_keygen/0,
crypto_secretstream_xchacha20poly1305_init_push/1,
crypto_secretstream_xchacha20poly1305_push/4,
crypto_secretstream_xchacha20poly1305_init_pull/2,
crypto_secretstream_xchacha20poly1305_pull/3,
crypto_secretstream_xchacha20poly1305_rekey/1
]).
%% Access to the RNG
-export([
randombytes/1,
@ -205,6 +223,21 @@ crypto_generichash_init(_HashSize, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_generichash_update(_HashState, _Message) -> erlang:nif_error(nif_not_loaded).
crypto_generichash_final(_HashState) -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_ABYTES() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_HEADERBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_KEYBYTES() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_TAG_PUSH() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_TAG_REKEY() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_TAG_FINAL() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_keygen() -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_init_push(_Key) -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_push(_Ref, _Message, _AD, _Tag) -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_init_pull(_Header, _Key) -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_pull(_Ref, _CipherText, _AD) -> erlang:nif_error(nif_not_loaded).
crypto_secretstream_xchacha20poly1305_rekey(_Ref) -> erlang:nif_error(nif_not_loaded).
crypto_pwhash(_Password, _Salt, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded).
crypto_pwhash_str(_Password, _Ops, _Mem) -> erlang:nif_error(nif_not_loaded).
crypto_pwhash_str_verify(_HashedPassword, _Password) -> erlang:nif_error(nif_not_loaded).