4095 lines
116 KiB
C++
4095 lines
116 KiB
C++
#include <assert.h>
|
|
#include <bare.h>
|
|
#include <js.h>
|
|
#include <jstl.h>
|
|
#include <sodium.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <uv.h>
|
|
|
|
#include "extensions/pbkdf2/pbkdf2.h"
|
|
#include "extensions/tweak/tweak.h"
|
|
|
|
#define assert_bounds(arraybuffer) \
|
|
assert(arraybuffer##_offset + arraybuffer##_len <= arraybuffer.size())
|
|
|
|
static inline void
|
|
sn_sodium_memzero(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> buf
|
|
) {
|
|
sodium_memzero(buf.data(), buf.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_sodium_mlock(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> buf
|
|
) {
|
|
return sodium_mlock(buf.data(), buf.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_sodium_munlock(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> buf
|
|
) {
|
|
return sodium_munlock(buf.data(), buf.size_bytes());
|
|
}
|
|
|
|
static void
|
|
sn_external_arraybuffer_finalize(js_env_t *env, uint8_t *ptr) {
|
|
sodium_free(ptr);
|
|
}
|
|
|
|
static js_arraybuffer_t
|
|
sn_sodium_malloc(js_env_t *env, js_receiver_t, uint32_t len) {
|
|
int err;
|
|
|
|
auto ptr = reinterpret_cast<uint8_t *>(sodium_malloc(len));
|
|
|
|
js_arraybuffer_t buffer;
|
|
|
|
err = js_create_external_arraybuffer<sn_external_arraybuffer_finalize>(env, ptr, len, buffer);
|
|
assert(err == 0);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static void
|
|
sn_sodium_free(js_env_t *env, js_receiver_t, js_arraybuffer_t buf) {
|
|
int err;
|
|
|
|
std::span<uint8_t> view;
|
|
err = js_get_arraybuffer_info(env, buf, view);
|
|
assert(err == 0);
|
|
|
|
if (view.empty()) return;
|
|
|
|
err = js_detach_arraybuffer(env, buf);
|
|
assert(err == 0);
|
|
}
|
|
|
|
static inline int
|
|
sn_sodium_mprotect_noaccess(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
|
|
return sodium_mprotect_noaccess(buf.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_sodium_mprotect_readonly(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
|
|
return sodium_mprotect_readonly(buf.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_sodium_mprotect_readwrite(js_env_t *env, js_receiver_t, js_arraybuffer_span_t buf) {
|
|
return sodium_mprotect_readwrite(buf.data());
|
|
}
|
|
|
|
static inline uint32_t // TODO: test envless
|
|
sn_randombytes_random(js_env_t *env, js_receiver_t) {
|
|
return randombytes_random();
|
|
}
|
|
|
|
static inline uint32_t // TODO: test envless
|
|
sn_randombytes_uniform(js_env_t *env, js_receiver_t, uint32_t upper_bound) {
|
|
return randombytes_uniform(upper_bound);
|
|
}
|
|
|
|
static inline void
|
|
sn_randombytes_buf(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
js_arraybuffer_span_t buf,
|
|
uint32_t buf_offset,
|
|
uint32_t buf_len
|
|
) {
|
|
assert_bounds(buf);
|
|
|
|
randombytes_buf(&buf[buf_offset], buf_len);
|
|
}
|
|
|
|
static inline void
|
|
sn_randombytes_buf_deterministic(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t buf,
|
|
uint32_t buf_offset,
|
|
uint32_t buf_len,
|
|
|
|
js_arraybuffer_span_t seed,
|
|
uint32_t seed_offset,
|
|
uint32_t seed_len
|
|
) {
|
|
assert_bounds(buf);
|
|
assert_bounds(seed);
|
|
|
|
assert(seed_len == randombytes_SEEDBYTES);
|
|
|
|
randombytes_buf_deterministic(&buf[buf_offset], buf_len, &seed[seed_offset]);
|
|
}
|
|
|
|
static inline bool
|
|
sn_sodium_memcmp(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
|
|
if (a.size_bytes() != b.size_bytes()) return false;
|
|
|
|
return sodium_memcmp(a.data(), b.data(), a.size_bytes()) == 0;
|
|
}
|
|
|
|
static inline void
|
|
sn_sodium_increment(js_env_t *, js_receiver_t, js_typedarray_span_t<> n) {
|
|
sodium_increment(n.data(), n.size_bytes());
|
|
}
|
|
|
|
static inline void
|
|
sn_sodium_add(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
|
|
sodium_add(a.data(), b.data(), a.size_bytes());
|
|
}
|
|
|
|
static inline void
|
|
sn_sodium_sub(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
|
|
sodium_sub(a.data(), b.data(), a.size_bytes());
|
|
}
|
|
|
|
static inline int32_t
|
|
sn_sodium_compare(js_env_t *, js_receiver_t, js_typedarray_span_t<> a, js_typedarray_span_t<> b) {
|
|
return sodium_compare(a.data(), b.data(), a.size_bytes());
|
|
}
|
|
|
|
static inline bool
|
|
sn_sodium_is_zero(js_env_t *, js_receiver_t, js_typedarray_span_t<> buffer, uint32_t len) {
|
|
assert(len <= buffer.size_bytes());
|
|
|
|
return sodium_is_zero(buffer.data(), len) != 0;
|
|
}
|
|
|
|
static inline uint32_t
|
|
sn_sodium_pad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t unpadded_buflen, uint32_t blocksize) {
|
|
size_t padded_buflen;
|
|
|
|
sodium_pad(&padded_buflen, buf.data(), unpadded_buflen, blocksize, buf.size_bytes());
|
|
|
|
return padded_buflen;
|
|
}
|
|
|
|
static inline uint32_t
|
|
sn_sodium_unpad(js_env_t *, js_receiver_t, js_typedarray_span_t<> buf, uint32_t padded_buflen, uint32_t blocksize) {
|
|
size_t unpadded_buflen;
|
|
|
|
sodium_unpad(&unpadded_buflen, buf.data(), padded_buflen, blocksize);
|
|
|
|
return unpadded_buflen;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
|
|
return crypto_sign_keypair(pk.data(), sk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_seed_keypair(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk,
|
|
js_typedarray_span_t<> seed
|
|
) {
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
assert(seed.size_bytes() == crypto_sign_SEEDBYTES);
|
|
|
|
return crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> sm,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(sm.size_bytes() == crypto_sign_BYTES + m.size_bytes());
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
|
|
return crypto_sign(sm.data(), NULL, m.data(), m.size_bytes(), sk.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_sign_open(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> sm,
|
|
js_typedarray_span_t<> pk
|
|
) {
|
|
assert(m.size_bytes() == sm.size_bytes() - crypto_sign_BYTES);
|
|
assert(sm.size_bytes() >= crypto_sign_BYTES);
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
|
|
return crypto_sign_open(m.data(), NULL, sm.data(), sm.size_bytes(), pk.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_detached(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> sig,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(sig.size_bytes() == crypto_sign_BYTES);
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
|
|
return crypto_sign_detached(sig.data(), NULL, m.data(), m.size_bytes(), sk.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_sign_verify_detached(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t sig,
|
|
uint32_t sig_offset,
|
|
uint32_t sig_len,
|
|
|
|
js_arraybuffer_span_t m,
|
|
uint32_t m_offset,
|
|
uint32_t m_len,
|
|
|
|
js_arraybuffer_span_t pk,
|
|
uint32_t pk_offset,
|
|
uint32_t pk_len
|
|
) {
|
|
assert_bounds(sig);
|
|
assert_bounds(m);
|
|
assert_bounds(pk);
|
|
|
|
assert(sig_len >= crypto_sign_BYTES);
|
|
assert(pk_len == crypto_sign_PUBLICKEYBYTES);
|
|
|
|
return crypto_sign_verify_detached(&sig[sig_offset], &m[m_offset], m_len, &pk[pk_offset]) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_ed25519_sk_to_pk(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
|
|
return crypto_sign_ed25519_sk_to_pk(pk.data(), sk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_ed25519_pk_to_curve25519(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> x25519_pk,
|
|
js_typedarray_span_t<> ed25519_pk
|
|
) {
|
|
assert(x25519_pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(ed25519_pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
|
|
return crypto_sign_ed25519_pk_to_curve25519(x25519_pk.data(), ed25519_pk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_sign_ed25519_sk_to_curve25519(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> x25519_sk,
|
|
js_typedarray_span_t<> ed25519_sk
|
|
) {
|
|
assert(x25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
assert(
|
|
ed25519_sk.size_bytes() == crypto_sign_SECRETKEYBYTES ||
|
|
ed25519_sk.size_bytes() == crypto_box_SECRETKEYBYTES
|
|
);
|
|
|
|
return crypto_sign_ed25519_sk_to_curve25519(x25519_sk.data(), ed25519_sk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_generichash(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_span_t in,
|
|
uint32_t in_offset,
|
|
uint32_t in_len,
|
|
|
|
js_arraybuffer_span_t key,
|
|
uint32_t key_offset,
|
|
uint32_t key_len
|
|
) {
|
|
assert_bounds(out);
|
|
assert(
|
|
out_len >= crypto_generichash_BYTES_MIN &&
|
|
out_len <= crypto_generichash_BYTES_MAX
|
|
);
|
|
|
|
assert_bounds(in);
|
|
|
|
uint8_t *key_data = NULL;
|
|
if (key_len) {
|
|
assert_bounds(key);
|
|
assert(
|
|
key_len >= crypto_generichash_KEYBYTES_MIN &&
|
|
key_len <= crypto_generichash_KEYBYTES_MAX
|
|
);
|
|
key_data = &key[key_offset];
|
|
}
|
|
|
|
return crypto_generichash(&out[out_offset], out_len, &in[in_offset], in_len, key_data, key_len);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_generichash_batch(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
js_typedarray_t<uint8_t> out,
|
|
std::vector<js_typedarray_span_t<>> batch,
|
|
bool use_key,
|
|
js_typedarray_t<uint8_t> key
|
|
) {
|
|
int err;
|
|
|
|
uint8_t *out_data;
|
|
size_t out_len;
|
|
err = js_get_typedarray_info(env, out, out_data, out_len);
|
|
assert(err == 0);
|
|
assert(
|
|
out_len >= crypto_generichash_BYTES_MIN &&
|
|
out_len <= crypto_generichash_BYTES_MAX
|
|
);
|
|
|
|
uint8_t *key_data = NULL;
|
|
size_t key_len = 0;
|
|
if (use_key) {
|
|
err = js_get_typedarray_info(env, key, key_data, key_len);
|
|
assert(err == 0);
|
|
assert(
|
|
key_len >= crypto_generichash_KEYBYTES_MIN &&
|
|
key_len <= crypto_generichash_KEYBYTES_MAX
|
|
);
|
|
}
|
|
|
|
crypto_generichash_state state;
|
|
err = crypto_generichash_init(&state, key_data, key_len, out_len);
|
|
if (err != 0) return err;
|
|
|
|
for (auto &buf : batch) {
|
|
err = crypto_generichash_update(&state, buf.data(), buf.size());
|
|
if (err != 0) return err;
|
|
}
|
|
|
|
return crypto_generichash_final(&state, out_data, out_len);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_generichash_keygen(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t key,
|
|
uint32_t key_offset,
|
|
uint32_t key_len
|
|
) {
|
|
assert_bounds(key);
|
|
assert(key_len == crypto_generichash_KEYBYTES);
|
|
|
|
crypto_generichash_keygen(&key[key_offset]);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_generichash_init(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t key,
|
|
uint32_t key_offset,
|
|
uint32_t key_len,
|
|
|
|
uint32_t out_len
|
|
) {
|
|
assert_bounds(state);
|
|
|
|
assert(state_len == sizeof(crypto_generichash_state));
|
|
|
|
uint8_t *key_data = NULL;
|
|
if (key_len) {
|
|
assert_bounds(key);
|
|
assert(
|
|
key_len >= crypto_generichash_KEYBYTES_MIN &&
|
|
key_len <= crypto_generichash_KEYBYTES_MAX
|
|
);
|
|
key_data = &key[key_offset];
|
|
}
|
|
|
|
auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
|
|
|
|
return crypto_generichash_init(state_data, key_data, key_len, out_len);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_generichash_update(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t in,
|
|
uint32_t in_offset,
|
|
uint32_t in_len
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(in);
|
|
|
|
assert(state_len == sizeof(crypto_generichash_state));
|
|
|
|
auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
|
|
|
|
return crypto_generichash_update(state_data, &in[in_offset], in_len);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_generichash_final(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(out);
|
|
|
|
assert(state_len == sizeof(crypto_generichash_state));
|
|
|
|
auto state_data = reinterpret_cast<crypto_generichash_state *>(&state[state_offset]);
|
|
|
|
return crypto_generichash_final(state_data, &out[out_offset], out_len);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_box_keypair(js_env_t *, js_receiver_t, js_typedarray_span_t<> pk, js_typedarray_span_t<> sk) {
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
|
|
return crypto_box_keypair(pk.data(), sk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_box_seed_keypair(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk,
|
|
js_typedarray_span_t<> seed
|
|
) {
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
assert(seed.size_bytes() == crypto_box_SEEDBYTES);
|
|
|
|
return crypto_box_seed_keypair(pk.data(), sk.data(), seed.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_box_easy(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes() + crypto_box_MACBYTES);
|
|
assert(n.size_bytes() == crypto_box_NONCEBYTES);
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
|
|
return crypto_box_easy(c.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_box_open_easy(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(c.size_bytes() >= crypto_box_MACBYTES);
|
|
assert(m.size_bytes() == c.size_bytes() - crypto_box_MACBYTES);
|
|
assert(n.size_bytes() == crypto_box_NONCEBYTES);
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
|
|
return crypto_box_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_box_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(mac.size_bytes() == crypto_box_MACBYTES);
|
|
assert(n.size_bytes() == crypto_box_NONCEBYTES);
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
|
|
return crypto_box_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), pk.data(), sk.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_box_open_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes());
|
|
assert(mac.size_bytes() == crypto_box_MACBYTES);
|
|
assert(n.size_bytes() == crypto_box_NONCEBYTES);
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_box_SECRETKEYBYTES);
|
|
|
|
return crypto_box_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), pk.data(), sk.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_box_seal(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> pk
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes() + crypto_box_SEALBYTES);
|
|
assert(pk.size_bytes() == crypto_box_PUBLICKEYBYTES);
|
|
|
|
return crypto_box_seal(c.data(), m.data(), m.size_bytes(), pk.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_box_seal_open(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t m,
|
|
uint32_t m_offset,
|
|
uint32_t m_len,
|
|
|
|
js_arraybuffer_span_t c,
|
|
uint32_t c_offset,
|
|
uint32_t c_len,
|
|
|
|
js_arraybuffer_span_t pk,
|
|
uint32_t pk_offset,
|
|
uint32_t pk_len,
|
|
|
|
js_arraybuffer_span_t sk,
|
|
uint32_t sk_offset,
|
|
uint32_t sk_len
|
|
) {
|
|
assert_bounds(m);
|
|
assert_bounds(c);
|
|
assert_bounds(pk);
|
|
assert_bounds(sk);
|
|
|
|
assert(m_len == c_len - crypto_box_SEALBYTES);
|
|
assert(c_len >= crypto_box_SEALBYTES);
|
|
assert(sk_len == crypto_box_SECRETKEYBYTES);
|
|
assert(pk_len == crypto_box_PUBLICKEYBYTES);
|
|
|
|
return crypto_box_seal_open(&m[m_offset], &c[c_offset], c_len, &pk[pk_offset], &sk[sk_offset]) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_secretbox_easy(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes() + crypto_secretbox_MACBYTES);
|
|
assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
|
|
|
|
return crypto_secretbox_easy(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_secretbox_open_easy(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes() - crypto_secretbox_MACBYTES);
|
|
assert(c.size_bytes() >= crypto_secretbox_MACBYTES);
|
|
assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
|
|
|
|
return crypto_secretbox_open_easy(m.data(), c.data(), c.size_bytes(), n.data(), k.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_secretbox_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
|
|
assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
|
|
|
|
return crypto_secretbox_detached(c.data(), mac.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_secretbox_open_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes());
|
|
assert(mac.size_bytes() == crypto_secretbox_MACBYTES);
|
|
assert(n.size_bytes() == crypto_secretbox_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_secretbox_KEYBYTES);
|
|
|
|
return crypto_secretbox_open_detached(m.data(), c.data(), mac.data(), c.size_bytes(), n.data(), k.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_KEYBYTES);
|
|
|
|
return crypto_stream(c.data(), c.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_xor(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t c,
|
|
uint32_t c_offset,
|
|
uint32_t c_len,
|
|
|
|
js_arraybuffer_span_t m,
|
|
uint32_t m_offset,
|
|
uint32_t m_len,
|
|
|
|
js_arraybuffer_span_t n,
|
|
uint32_t n_offset,
|
|
uint32_t n_len,
|
|
|
|
js_arraybuffer_span_t k,
|
|
uint32_t k_offset,
|
|
uint32_t k_len
|
|
) {
|
|
assert_bounds(c);
|
|
assert_bounds(m);
|
|
assert_bounds(n);
|
|
assert_bounds(k);
|
|
|
|
assert(c_len == m_len);
|
|
assert(n_len == crypto_stream_NONCEBYTES);
|
|
assert(k_len == crypto_stream_KEYBYTES);
|
|
|
|
return crypto_stream_xor(&c[c_offset], &m[m_offset], m_len, &n[n_offset], &k[k_offset]);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20(c.data(), c.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20_xor(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20_xor_ic(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
uint32_t ic,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20_ietf(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20_ietf(c.data(), c.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20_ietf_xor(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20_ietf_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_chacha20_ietf_xor_ic(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
uint32_t ic,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
|
|
|
|
return crypto_stream_chacha20_ietf_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_xchacha20(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
|
|
|
|
return crypto_stream_xchacha20(c.data(), c.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_xchacha20_xor(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
|
|
|
|
return crypto_stream_xchacha20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_xchacha20_xor_ic(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
uint32_t ic,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
|
|
|
|
return crypto_stream_xchacha20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_salsa20(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
|
|
|
|
return crypto_stream_salsa20(c.data(), c.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_salsa20_xor(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
|
|
|
|
return crypto_stream_salsa20_xor(c.data(), m.data(), m.size_bytes(), n.data(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_stream_salsa20_xor_ic(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> n,
|
|
uint32_t ic,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
|
|
|
|
return crypto_stream_salsa20_xor_ic(c.data(), m.data(), m.size_bytes(), n.data(), ic, k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_auth(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(out.size_bytes() == crypto_auth_BYTES);
|
|
assert(k.size_bytes() == crypto_auth_KEYBYTES);
|
|
|
|
return crypto_auth(out.data(), in.data(), in.size_bytes(), k.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_auth_verify(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> h,
|
|
js_typedarray_span_t<> in,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(h.size_bytes() == crypto_auth_BYTES);
|
|
assert(k.size_bytes() == crypto_auth_KEYBYTES);
|
|
|
|
return crypto_auth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_onetimeauth(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(out.size_bytes() == crypto_onetimeauth_BYTES);
|
|
assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
|
|
|
|
return crypto_onetimeauth(out.data(), in.data(), in.size_bytes(), k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_onetimeauth_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
|
|
|
|
return crypto_onetimeauth_init(&*state, k.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_onetimeauth_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
return crypto_onetimeauth_update(&*state, in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_onetimeauth_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_onetimeauth_state, 1> state,
|
|
js_typedarray_span_t<> out
|
|
) {
|
|
assert(out.size_bytes() == crypto_onetimeauth_BYTES);
|
|
|
|
return crypto_onetimeauth_final(&*state, out.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_onetimeauth_verify(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> h,
|
|
js_typedarray_span_t<> in,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(h.size_bytes() == crypto_onetimeauth_BYTES);
|
|
assert(k.size_bytes() == crypto_onetimeauth_KEYBYTES);
|
|
|
|
return crypto_onetimeauth_verify(h.data(), in.data(), in.size_bytes(), k.data()) == 0;
|
|
}
|
|
|
|
// CHECK: memlimit can be >32bit
|
|
static inline int
|
|
sn_crypto_pwhash(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_of_t<char> passwd,
|
|
js_typedarray_span_t<> salt,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit,
|
|
int32_t alg
|
|
) {
|
|
assert(out.size_bytes() >= crypto_pwhash_BYTES_MIN);
|
|
assert(out.size_bytes() <= crypto_pwhash_BYTES_MAX);
|
|
assert(salt.size_bytes() == crypto_pwhash_SALTBYTES);
|
|
assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
|
|
assert(alg == 1 || alg == 2); // Argon2i or Argon2id
|
|
|
|
return crypto_pwhash(
|
|
out.data(),
|
|
out.size_bytes(),
|
|
passwd.data(),
|
|
passwd.size_bytes(),
|
|
salt.data(),
|
|
opslimit,
|
|
memlimit,
|
|
alg
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_pwhash_str(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> out,
|
|
js_typedarray_span_of_t<char> passwd,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit
|
|
) {
|
|
assert(out.size_bytes() == crypto_pwhash_STRBYTES);
|
|
assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
|
|
|
|
return crypto_pwhash_str(
|
|
out.data(),
|
|
passwd.data(),
|
|
passwd.size_bytes(),
|
|
opslimit,
|
|
memlimit
|
|
);
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_pwhash_str_verify(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> str,
|
|
js_typedarray_span_of_t<char> passwd
|
|
) {
|
|
assert(str.size_bytes() == crypto_pwhash_STRBYTES);
|
|
|
|
return crypto_pwhash_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
|
|
}
|
|
|
|
// CHECK: returns 1, 0, -1
|
|
static inline bool
|
|
sn_crypto_pwhash_str_needs_rehash(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> str,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit
|
|
) {
|
|
assert(str.size_bytes() == crypto_pwhash_STRBYTES);
|
|
assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
|
|
|
|
return crypto_pwhash_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
|
|
}
|
|
|
|
// CHECK: memlimit can be >32bit
|
|
static inline int
|
|
sn_crypto_pwhash_scryptsalsa208sha256(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_of_t<char> passwd,
|
|
js_typedarray_span_t<> salt,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit
|
|
) {
|
|
assert(out.size_bytes() >= crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
|
|
assert(out.size_bytes() <= crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
|
|
assert(salt.size_bytes() == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
|
assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
|
|
|
|
return crypto_pwhash_scryptsalsa208sha256(
|
|
out.data(),
|
|
out.size_bytes(),
|
|
passwd.data(),
|
|
passwd.size_bytes(),
|
|
salt.data(),
|
|
opslimit,
|
|
memlimit
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_pwhash_scryptsalsa208sha256_str(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> out,
|
|
js_typedarray_span_of_t<char> passwd,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit
|
|
) {
|
|
assert(out.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
|
|
assert(opslimit >= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
|
|
|
|
return crypto_pwhash_scryptsalsa208sha256_str(
|
|
out.data(),
|
|
passwd.data(),
|
|
passwd.size_bytes(),
|
|
opslimit,
|
|
memlimit
|
|
);
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_pwhash_scryptsalsa208sha256_str_verify(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> str,
|
|
js_typedarray_span_of_t<char> passwd
|
|
) {
|
|
assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
|
|
|
|
return crypto_pwhash_scryptsalsa208sha256_str_verify(str.data(), passwd.data(), passwd.size_bytes()) == 0;
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<char> str,
|
|
uint64_t opslimit,
|
|
uint64_t memlimit
|
|
) {
|
|
assert(str.size_bytes() == crypto_pwhash_scryptsalsa208sha256_STRBYTES);
|
|
assert(opslimit >= crypto_pwhash_OPSLIMIT_MIN);
|
|
assert(opslimit <= crypto_pwhash_OPSLIMIT_MAX);
|
|
assert(memlimit >= crypto_pwhash_MEMLIMIT_MIN);
|
|
assert(memlimit <= crypto_pwhash_MEMLIMIT_MAX);
|
|
|
|
return crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str.data(), opslimit, memlimit) != 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_kx_keypair(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
|
|
|
|
return crypto_kx_keypair(pk.data(), sk.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_kx_seed_keypair(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> sk,
|
|
js_typedarray_span_t<> seed
|
|
) {
|
|
assert(pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
assert(sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
|
|
assert(seed.size_bytes() == crypto_kx_SEEDBYTES);
|
|
|
|
return crypto_kx_seed_keypair(pk.data(), sk.data(), seed.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_kx_client_session_keys(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
std::optional<js_typedarray_span_t<>> rx,
|
|
std::optional<js_typedarray_span_t<>> tx,
|
|
js_typedarray_span_t<> client_pk,
|
|
js_typedarray_span_t<> client_sk,
|
|
js_typedarray_span_t<> server_pk
|
|
) {
|
|
assert(rx.has_value() || tx.has_value());
|
|
|
|
if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
|
|
if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
|
|
|
|
assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
assert(client_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
|
|
assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
|
|
return crypto_kx_client_session_keys(
|
|
rx ? rx->data() : nullptr,
|
|
tx ? tx->data() : nullptr,
|
|
client_pk.data(),
|
|
client_sk.data(),
|
|
server_pk.data()
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_kx_server_session_keys(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
std::optional<js_typedarray_span_t<>> rx,
|
|
std::optional<js_typedarray_span_t<>> tx,
|
|
js_typedarray_span_t<> server_pk,
|
|
js_typedarray_span_t<> server_sk,
|
|
js_typedarray_span_t<> client_pk
|
|
) {
|
|
assert(rx.has_value() || tx.has_value());
|
|
|
|
if (rx) assert(rx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
|
|
if (tx) assert(tx->size_bytes() == crypto_kx_SESSIONKEYBYTES);
|
|
|
|
assert(server_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
assert(server_sk.size_bytes() == crypto_kx_SECRETKEYBYTES);
|
|
assert(client_pk.size_bytes() == crypto_kx_PUBLICKEYBYTES);
|
|
|
|
return crypto_kx_server_session_keys(
|
|
rx ? rx->data() : nullptr,
|
|
tx ? tx->data() : nullptr,
|
|
server_pk.data(),
|
|
server_sk.data(),
|
|
client_pk.data()
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult_base(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
|
|
|
|
return crypto_scalarmult_base(q.data(), n.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> p
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_SCALARBYTES);
|
|
assert(p.size_bytes() == crypto_scalarmult_BYTES);
|
|
|
|
return crypto_scalarmult(q.data(), n.data(), p.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult_ed25519_base(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
|
|
|
|
return crypto_scalarmult_ed25519_base(q.data(), n.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult_ed25519(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> p
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
|
|
assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
|
|
return crypto_scalarmult_ed25519(q.data(), n.data(), p.data());
|
|
}
|
|
|
|
static inline bool
|
|
sn_crypto_core_ed25519_is_valid_point(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> p
|
|
) {
|
|
assert(p.size_bytes() == crypto_core_ed25519_BYTES);
|
|
|
|
return crypto_core_ed25519_is_valid_point(p.data()) != 0;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_core_ed25519_from_uniform(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> p,
|
|
js_typedarray_span_t<> r
|
|
) {
|
|
assert(p.size_bytes() == crypto_core_ed25519_BYTES);
|
|
assert(r.size_bytes() == crypto_core_ed25519_UNIFORMBYTES);
|
|
|
|
return crypto_core_ed25519_from_uniform(p.data(), r.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult_ed25519_base_noclamp(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
|
|
|
|
return crypto_scalarmult_ed25519_base_noclamp(q.data(), n.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_scalarmult_ed25519_noclamp(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> q,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> p
|
|
) {
|
|
assert(q.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
assert(n.size_bytes() == crypto_scalarmult_ed25519_SCALARBYTES);
|
|
assert(p.size_bytes() == crypto_scalarmult_ed25519_BYTES);
|
|
|
|
return crypto_scalarmult_ed25519_noclamp(q.data(), n.data(), p.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_core_ed25519_add(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> r,
|
|
js_typedarray_span_t<> p,
|
|
js_typedarray_span_t<> q
|
|
) {
|
|
assert(r.size_bytes() == crypto_core_ed25519_BYTES);
|
|
assert(p.size_bytes() == crypto_core_ed25519_BYTES);
|
|
assert(q.size_bytes() == crypto_core_ed25519_BYTES);
|
|
|
|
return crypto_core_ed25519_add(r.data(), p.data(), q.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_core_ed25519_sub(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> r,
|
|
js_typedarray_span_t<> p,
|
|
js_typedarray_span_t<> q
|
|
) {
|
|
assert(r.size_bytes() == crypto_core_ed25519_BYTES);
|
|
assert(p.size_bytes() == crypto_core_ed25519_BYTES);
|
|
assert(q.size_bytes() == crypto_core_ed25519_BYTES);
|
|
|
|
return crypto_core_ed25519_sub(r.data(), p.data(), q.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_random(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> r
|
|
) {
|
|
assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_random(r.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_reduce(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> r,
|
|
js_typedarray_span_t<> s
|
|
) {
|
|
assert(r.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(s.size_bytes() == crypto_core_ed25519_NONREDUCEDSCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_reduce(r.data(), s.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_invert(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> recip,
|
|
js_typedarray_span_t<> s
|
|
) {
|
|
assert(recip.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_invert(recip.data(), s.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_negate(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> neg,
|
|
js_typedarray_span_t<> s
|
|
) {
|
|
assert(neg.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_negate(neg.data(), s.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_complement(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> comp,
|
|
js_typedarray_span_t<> s
|
|
) {
|
|
assert(comp.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(s.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_complement(comp.data(), s.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_add(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> z,
|
|
js_typedarray_span_t<> x,
|
|
js_typedarray_span_t<> y
|
|
) {
|
|
assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_add(z.data(), x.data(), y.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_core_ed25519_scalar_sub(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> z,
|
|
js_typedarray_span_t<> x,
|
|
js_typedarray_span_t<> y
|
|
) {
|
|
assert(z.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(x.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
assert(y.size_bytes() == crypto_core_ed25519_SCALARBYTES);
|
|
|
|
crypto_core_ed25519_scalar_sub(z.data(), x.data(), y.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_shorthash(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(out.size_bytes() == crypto_shorthash_BYTES);
|
|
assert(k.size_bytes() == crypto_shorthash_KEYBYTES);
|
|
|
|
return crypto_shorthash(out.data(), in.data(), in.size_bytes(), k.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_kdf_keygen(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> key
|
|
) {
|
|
assert(key.size_bytes() == crypto_kdf_KEYBYTES);
|
|
|
|
crypto_kdf_keygen(key.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_kdf_derive_from_key(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> subkey,
|
|
uint64_t subkey_id,
|
|
js_typedarray_span_of_t<char> ctx,
|
|
js_typedarray_span_t<> key
|
|
) {
|
|
assert(subkey.size_bytes() >= crypto_kdf_BYTES_MIN);
|
|
assert(subkey.size_bytes() <= crypto_kdf_BYTES_MAX);
|
|
assert(ctx.size_bytes() == crypto_kdf_CONTEXTBYTES);
|
|
assert(key.size_bytes() == crypto_kdf_KEYBYTES);
|
|
|
|
return crypto_kdf_derive_from_key(
|
|
subkey.data(),
|
|
subkey.size_bytes(),
|
|
subkey_id,
|
|
ctx.data(),
|
|
key.data()
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
assert(out.size_bytes() == crypto_hash_BYTES);
|
|
|
|
return crypto_hash(out.data(), in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha256(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
assert(out.size_bytes() == crypto_hash_sha256_BYTES);
|
|
|
|
return crypto_hash_sha256(out.data(), in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha256_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state
|
|
) {
|
|
return crypto_hash_sha256_init(&*state);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha256_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
return crypto_hash_sha256_update(&*state, in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha256_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha256_state, 1> state,
|
|
js_typedarray_span_t<> out
|
|
) {
|
|
assert(out.size_bytes() == crypto_hash_sha256_BYTES);
|
|
|
|
return crypto_hash_sha256_final(&*state, out.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha512(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
assert(out.size_bytes() == crypto_hash_sha512_BYTES);
|
|
|
|
return crypto_hash_sha512(out.data(), in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha512_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state
|
|
) {
|
|
return crypto_hash_sha512_init(&*state);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha512_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
|
|
js_typedarray_span_t<> in
|
|
) {
|
|
return crypto_hash_sha512_update(&*state, in.data(), in.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_hash_sha512_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<crypto_hash_sha512_state, 1> state,
|
|
js_typedarray_span_t<> out
|
|
) {
|
|
assert(out.size_bytes() == crypto_hash_sha512_BYTES);
|
|
|
|
return crypto_hash_sha512_final(&*state, out.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_aead_xchacha20poly1305_ietf_keygen(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
|
|
crypto_aead_xchacha20poly1305_ietf_keygen(k.data());
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes() + crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
assert(c.size_bytes() <= 0xffffffff);
|
|
assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long clen = 0;
|
|
int status = crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
c.data(),
|
|
&clen,
|
|
m.data(),
|
|
m.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
nullptr,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return clen;
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes() - crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
assert(m.size_bytes() <= 0xffffffff);
|
|
assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long mlen = 0;
|
|
int status = crypto_aead_xchacha20poly1305_ietf_decrypt(
|
|
m.data(),
|
|
&mlen,
|
|
nullptr,
|
|
c.data(),
|
|
c.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return mlen;
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> m,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long maclen = 0;
|
|
int status = crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
|
|
c.data(),
|
|
mac.data(),
|
|
&maclen,
|
|
m.data(),
|
|
m.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
nullptr,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return maclen;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes());
|
|
assert(mac.size_bytes() == crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
assert(npub.size_bytes() == crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
|
|
m.data(),
|
|
nullptr,
|
|
c.data(),
|
|
c.size_bytes(),
|
|
mac.data(),
|
|
ad_data,
|
|
ad_size,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_aead_chacha20poly1305_ietf_keygen(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
|
|
crypto_aead_chacha20poly1305_ietf_keygen(k.data());
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_chacha20poly1305_ietf_encrypt(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes() + crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
assert(c.size_bytes() <= 0xffffffff);
|
|
assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long clen = 0;
|
|
int status = crypto_aead_chacha20poly1305_ietf_encrypt(
|
|
c.data(),
|
|
&clen,
|
|
m.data(),
|
|
m.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
nullptr,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return clen;
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_chacha20poly1305_ietf_decrypt(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes() - crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
assert(m.size_bytes() <= 0xffffffff);
|
|
assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long mlen = 0;
|
|
int status = crypto_aead_chacha20poly1305_ietf_decrypt(
|
|
m.data(),
|
|
&mlen,
|
|
nullptr,
|
|
c.data(),
|
|
c.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return mlen;
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
js_typedarray_span_t<> m,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
unsigned long long maclen = 0;
|
|
int status = crypto_aead_chacha20poly1305_ietf_encrypt_detached(
|
|
c.data(),
|
|
mac.data(),
|
|
&maclen,
|
|
m.data(),
|
|
m.size_bytes(),
|
|
ad_data,
|
|
ad_size,
|
|
nullptr,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return maclen;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> mac,
|
|
std::optional<js_typedarray_span_t<>> ad,
|
|
js_typedarray_span_t<> npub,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(m.size_bytes() == c.size_bytes());
|
|
assert(mac.size_bytes() == crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
assert(npub.size_bytes() == crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
assert(k.size_bytes() == crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
|
|
uint8_t *ad_data = nullptr;
|
|
size_t ad_size = 0;
|
|
if (ad) {
|
|
ad_data = ad->data();
|
|
ad_size = ad->size_bytes();
|
|
}
|
|
|
|
return crypto_aead_chacha20poly1305_ietf_decrypt_detached(
|
|
m.data(),
|
|
nullptr,
|
|
c.data(),
|
|
c.size_bytes(),
|
|
mac.data(),
|
|
ad_data,
|
|
ad_size,
|
|
npub.data(),
|
|
k.data()
|
|
);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_secretstream_xchacha20poly1305_keygen(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t k,
|
|
uint32_t k_offset,
|
|
uint32_t k_len
|
|
) {
|
|
assert_bounds(k);
|
|
assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
|
|
|
crypto_secretstream_xchacha20poly1305_keygen(&k[k_offset]);
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_secretstream_xchacha20poly1305_init_push(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t header,
|
|
uint32_t header_offset,
|
|
uint32_t header_len,
|
|
|
|
js_arraybuffer_span_t k,
|
|
uint32_t k_offset,
|
|
uint32_t k_len
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(header);
|
|
assert_bounds(k);
|
|
|
|
assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
|
|
assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
|
|
|
auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
|
|
|
|
return crypto_secretstream_xchacha20poly1305_init_push(state_data, &header[header_offset], &k[k_offset]);
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_secretstream_xchacha20poly1305_push(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t c,
|
|
uint32_t c_offset,
|
|
uint32_t c_len,
|
|
|
|
js_arraybuffer_span_t m,
|
|
uint32_t m_offset,
|
|
uint32_t m_len,
|
|
|
|
js_arraybuffer_span_t ad,
|
|
uint32_t ad_offset,
|
|
uint32_t ad_len,
|
|
|
|
uint32_t tag
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(c);
|
|
assert_bounds(m);
|
|
|
|
assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
assert(c_len == m_len + crypto_secretstream_xchacha20poly1305_ABYTES);
|
|
assert(c_len <= 0xffffffff && "32bit integer");
|
|
|
|
auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
|
|
|
|
uint8_t *ad_data = NULL;
|
|
if (ad_len) {
|
|
assert_bounds(ad);
|
|
ad_data = &ad[ad_offset];
|
|
}
|
|
|
|
unsigned long long clen = 0;
|
|
int status = crypto_secretstream_xchacha20poly1305_push(
|
|
state_data,
|
|
&c[c_offset],
|
|
&clen,
|
|
&m[m_offset],
|
|
m_len,
|
|
ad_data,
|
|
ad_len,
|
|
tag
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return clen;
|
|
}
|
|
|
|
static inline int
|
|
sn_crypto_secretstream_xchacha20poly1305_init_pull(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t header,
|
|
uint32_t header_offset,
|
|
uint32_t header_len,
|
|
|
|
js_arraybuffer_span_t k,
|
|
uint32_t k_offset,
|
|
uint32_t k_len
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(header);
|
|
assert_bounds(k);
|
|
|
|
assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
assert(header_len == crypto_secretstream_xchacha20poly1305_HEADERBYTES);
|
|
assert(k_len == crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
|
|
|
auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
|
|
|
|
return crypto_secretstream_xchacha20poly1305_init_pull(state_data, &header[header_offset], &k[k_offset]);
|
|
}
|
|
|
|
static inline uint64_t
|
|
sn_crypto_secretstream_xchacha20poly1305_pull(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len,
|
|
|
|
js_arraybuffer_span_t m,
|
|
uint32_t m_offset,
|
|
uint32_t m_len,
|
|
|
|
js_arraybuffer_span_t tag,
|
|
uint32_t tag_offset,
|
|
uint32_t tag_len,
|
|
|
|
js_arraybuffer_span_t c,
|
|
uint32_t c_offset,
|
|
uint32_t c_len,
|
|
|
|
js_arraybuffer_span_t ad,
|
|
uint32_t ad_offset,
|
|
uint32_t ad_len
|
|
) {
|
|
assert_bounds(state);
|
|
assert_bounds(m);
|
|
assert_bounds(tag);
|
|
assert_bounds(c);
|
|
|
|
assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
assert(c_len >= crypto_secretstream_xchacha20poly1305_ABYTES);
|
|
assert(tag_len == 1);
|
|
assert(m_len == c_len - crypto_secretstream_xchacha20poly1305_ABYTES);
|
|
assert(m_len <= 0xffffffff);
|
|
|
|
auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
|
|
|
|
uint8_t *ad_data = NULL;
|
|
if (ad_len) {
|
|
assert_bounds(ad);
|
|
ad_data = &ad[ad_offset];
|
|
}
|
|
|
|
unsigned long long mlen = 0;
|
|
int status = crypto_secretstream_xchacha20poly1305_pull(
|
|
state_data,
|
|
&m[m_offset],
|
|
&mlen,
|
|
&tag[tag_offset],
|
|
&c[c_offset],
|
|
c_len,
|
|
ad_data,
|
|
ad_len
|
|
);
|
|
|
|
if (status < 0) return status;
|
|
|
|
return mlen;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_secretstream_xchacha20poly1305_rekey(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_span_t state,
|
|
uint32_t state_offset,
|
|
uint32_t state_len
|
|
) {
|
|
assert_bounds(state);
|
|
|
|
assert(state_len == sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
|
|
auto state_data = reinterpret_cast<crypto_secretstream_xchacha20poly1305_state *>(&state[state_offset]);
|
|
|
|
crypto_secretstream_xchacha20poly1305_rekey(state_data);
|
|
}
|
|
|
|
struct sn_async_task {
|
|
uv_work_t task;
|
|
js_env_t *env;
|
|
js_persistent_t<js_function_t<void, int>> cb;
|
|
js_deferred_teardown_t *teardown;
|
|
int code = 0;
|
|
bool exiting = false;
|
|
|
|
sn_async_task(js_env_t *env) : env(env) {
|
|
int err;
|
|
err = js_add_teardown_callback<on_teardown, sn_async_task>(env, this, teardown);
|
|
assert(err == 0);
|
|
}
|
|
|
|
~sn_async_task() {
|
|
int err;
|
|
err = js_finish_teardown_callback(teardown);
|
|
assert(err == 0);
|
|
}
|
|
|
|
private:
|
|
static void
|
|
on_teardown(js_deferred_teardown_t *teardown, sn_async_task *req) {
|
|
req->exiting = true;
|
|
}
|
|
};
|
|
|
|
struct sn_async_pwhash_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> out_ref;
|
|
std::span<uint8_t> out;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
js_persistent_t<js_arraybuffer_t> salt_ref;
|
|
std::span<uint8_t> salt;
|
|
|
|
uint64_t opslimit;
|
|
size_t memlimit;
|
|
int alg;
|
|
|
|
sn_async_pwhash_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_execute(uv_work_t *uv_req) {
|
|
auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash(
|
|
req->out.data(),
|
|
req->out.size(),
|
|
req->pwd.data(),
|
|
req->pwd.size(),
|
|
req->salt.data(),
|
|
req->opslimit,
|
|
req->memlimit,
|
|
req->alg
|
|
);
|
|
}
|
|
|
|
static void
|
|
async_pwhash_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto req = reinterpret_cast<sn_async_pwhash_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
js_arraybuffer_t salt,
|
|
uint32_t salt_offset,
|
|
uint32_t salt_len,
|
|
|
|
uint64_t opslimit,
|
|
uint64_t memlimit,
|
|
uint32_t alg,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_request(env);
|
|
|
|
std::span<uint8_t> out_view;
|
|
err = js_get_arraybuffer_info(env, out, out_view);
|
|
assert(err == 0);
|
|
assert(out_offset + out_len <= out_view.size());
|
|
|
|
req->out = {&out_view[out_offset], out_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
std::span<uint8_t> salt_view;
|
|
err = js_get_arraybuffer_info(env, salt, salt_view);
|
|
assert(err == 0);
|
|
assert(salt_offset + salt_len <= salt_view.size());
|
|
|
|
req->salt = {&salt_view[salt_offset], salt_len};
|
|
|
|
req->opslimit = opslimit;
|
|
req->memlimit = memlimit;
|
|
req->alg = alg;
|
|
|
|
err = js_create_reference(env, out, req->out_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, salt, req->salt_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_execute, async_pwhash_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_async_pwhash_str_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> out_ref;
|
|
std::span<char> out;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
uint64_t opslimit;
|
|
size_t memlimit;
|
|
|
|
sn_async_pwhash_str_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_str_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash_str(
|
|
req->out.data(),
|
|
req->pwd.data(),
|
|
req->pwd.size(),
|
|
req->opslimit,
|
|
req->memlimit
|
|
);
|
|
}
|
|
|
|
static void
|
|
async_pwhash_str_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pwhash_str_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_str_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
uint64_t opslimit,
|
|
uint64_t memlimit,
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_str_request(env);
|
|
|
|
std::span<char> out_view;
|
|
err = js_get_arraybuffer_info(env, out, out_view);
|
|
assert(err == 0);
|
|
assert(out_offset + out_len <= out_view.size());
|
|
|
|
req->out = {&out_view[out_offset], out_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
req->opslimit = opslimit;
|
|
req->memlimit = memlimit;
|
|
|
|
err = js_create_reference(env, out, req->out_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_str_execute, async_pwhash_str_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_async_pwhash_str_verify_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> str_ref;
|
|
std::span<char> str;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
sn_async_pwhash_str_verify_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_str_verify_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
|
|
}
|
|
|
|
static void
|
|
async_pwhash_str_verify_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pwhash_str_verify_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_str_verify_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t str,
|
|
uint32_t str_offset,
|
|
uint32_t str_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_str_verify_request(env);
|
|
|
|
std::span<char> str_view;
|
|
err = js_get_arraybuffer_info(env, str, str_view);
|
|
assert(err == 0);
|
|
assert(str_offset + str_len <= str_view.size());
|
|
|
|
req->str = {&str_view[str_offset], str_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
err = js_create_reference(env, str, req->str_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_str_verify_execute, async_pwhash_str_verify_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_async_pwhash_scryptsalsa208sha256_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> out_ref;
|
|
std::span<uint8_t> out;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
js_persistent_t<js_arraybuffer_t> salt_ref;
|
|
std::span<uint8_t> salt;
|
|
|
|
uint64_t opslimit;
|
|
size_t memlimit;
|
|
|
|
sn_async_pwhash_scryptsalsa208sha256_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash_scryptsalsa208sha256(
|
|
req->out.data(),
|
|
req->out.size(),
|
|
req->pwd.data(),
|
|
req->pwd.size(),
|
|
req->salt.data(),
|
|
req->opslimit,
|
|
req->memlimit
|
|
);
|
|
}
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_scryptsalsa208sha256_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
js_arraybuffer_t salt,
|
|
uint32_t salt_offset,
|
|
uint32_t salt_len,
|
|
|
|
uint64_t opslimit,
|
|
uint64_t memlimit,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_scryptsalsa208sha256_request(env);
|
|
|
|
std::span<uint8_t> out_view;
|
|
err = js_get_arraybuffer_info(env, out, out_view);
|
|
assert(err == 0);
|
|
assert(out_offset + out_len <= out_view.size());
|
|
|
|
req->out = {&out_view[out_offset], out_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
std::span<uint8_t> salt_view;
|
|
err = js_get_arraybuffer_info(env, salt, salt_view);
|
|
assert(err == 0);
|
|
assert(salt_offset + salt_len <= salt_view.size());
|
|
assert(salt_len == crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
|
|
|
req->salt = {&salt_view[salt_offset], salt_len};
|
|
|
|
req->opslimit = opslimit;
|
|
req->memlimit = memlimit;
|
|
|
|
err = js_create_reference(env, out, req->out_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, salt, req->salt_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_execute, async_pwhash_scryptsalsa208sha256_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_async_pwhash_scryptsalsa208sha256_str_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> out_ref;
|
|
std::span<char> out;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
uint64_t opslimit;
|
|
size_t memlimit;
|
|
|
|
sn_async_pwhash_scryptsalsa208sha256_str_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_str_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash_scryptsalsa208sha256_str(
|
|
req->out.data(),
|
|
req->pwd.data(),
|
|
req->pwd.size(),
|
|
req->opslimit,
|
|
req->memlimit
|
|
);
|
|
}
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_str_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_scryptsalsa208sha256_str_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
uint64_t opslimit,
|
|
uint64_t memlimit,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_request(env);
|
|
|
|
std::span<char> out_view;
|
|
err = js_get_arraybuffer_info(env, out, out_view);
|
|
assert(err == 0);
|
|
assert(out_offset + out_len <= out_view.size());
|
|
|
|
req->out = {&out_view[out_offset], out_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
req->opslimit = opslimit;
|
|
req->memlimit = memlimit;
|
|
|
|
err = js_create_reference(env, out, req->out_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_execute, async_pwhash_scryptsalsa208sha256_str_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_async_pwhash_scryptsalsa208sha256_str_verify_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> str_ref;
|
|
std::span<char> str;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<char> pwd;
|
|
|
|
sn_async_pwhash_scryptsalsa208sha256_str_verify_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_str_verify_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
|
|
|
|
req->code = crypto_pwhash_scryptsalsa208sha256_str_verify(req->str.data(), req->pwd.data(), req->pwd.size());
|
|
}
|
|
|
|
static void
|
|
async_pwhash_scryptsalsa208sha256_str_verify_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pwhash_scryptsalsa208sha256_str_verify_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t str,
|
|
uint32_t str_offset,
|
|
uint32_t str_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pwhash_scryptsalsa208sha256_str_verify_request(env);
|
|
|
|
std::span<char> str_view;
|
|
err = js_get_arraybuffer_info(env, str, str_view);
|
|
assert(err == 0);
|
|
assert(str_offset + str_len <= str_view.size());
|
|
|
|
req->str = {&str_view[str_offset], str_len};
|
|
|
|
std::span<char> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
err = js_create_reference(env, str, req->str_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pwhash_scryptsalsa208sha256_str_verify_execute, async_pwhash_scryptsalsa208sha256_str_verify_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
struct sn_crypto_stream_xor_state {
|
|
unsigned char n[crypto_stream_NONCEBYTES];
|
|
unsigned char k[crypto_stream_KEYBYTES];
|
|
unsigned char next_block[64];
|
|
int remainder;
|
|
uint64_t block_counter;
|
|
};
|
|
|
|
static inline void
|
|
sn_crypto_stream_xor_wrap_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_KEYBYTES);
|
|
|
|
state->remainder = 0;
|
|
state->block_counter = 0;
|
|
memcpy(state->n, n.data(), crypto_stream_NONCEBYTES);
|
|
memcpy(state->k, k.data(), crypto_stream_KEYBYTES);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_xor_wrap_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
|
|
auto next_block = state->next_block;
|
|
|
|
size_t m_size = m.size_bytes();
|
|
auto *c_ptr = c.data();
|
|
auto *m_ptr = m.data();
|
|
|
|
if (state->remainder) {
|
|
uint64_t offset = 0;
|
|
int rem = state->remainder;
|
|
|
|
while (rem < 64 && offset < m_size) {
|
|
c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
|
|
++offset;
|
|
++rem;
|
|
}
|
|
|
|
c_ptr += offset;
|
|
m_ptr += offset;
|
|
m_size -= offset;
|
|
state->remainder = (rem == 64) ? 0 : rem;
|
|
|
|
if (m_size == 0) return;
|
|
}
|
|
|
|
state->remainder = m_size & 63;
|
|
size_t main_len = m_size - state->remainder;
|
|
|
|
crypto_stream_xsalsa20_xor_ic(c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k);
|
|
state->block_counter += main_len / 64;
|
|
|
|
if (state->remainder) {
|
|
sodium_memzero(next_block + state->remainder, 64 - state->remainder);
|
|
memcpy(next_block, m_ptr + main_len, state->remainder);
|
|
|
|
crypto_stream_xsalsa20_xor_ic(
|
|
next_block, next_block, 64, state->n, state->block_counter, state->k
|
|
);
|
|
memcpy(c_ptr + main_len, next_block, state->remainder);
|
|
|
|
state->block_counter++;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_xor_wrap_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xor_state, 1> state
|
|
) {
|
|
sodium_memzero(state->n, sizeof(state->n));
|
|
sodium_memzero(state->k, sizeof(state->k));
|
|
sodium_memzero(state->next_block, sizeof(state->next_block));
|
|
state->remainder = 0;
|
|
}
|
|
|
|
struct sn_crypto_stream_chacha20_xor_state {
|
|
unsigned char n[crypto_stream_chacha20_NONCEBYTES];
|
|
unsigned char k[crypto_stream_chacha20_KEYBYTES];
|
|
unsigned char next_block[64];
|
|
int remainder;
|
|
uint64_t block_counter;
|
|
};
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_xor_wrap_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_chacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_KEYBYTES);
|
|
|
|
state->remainder = 0;
|
|
state->block_counter = 0;
|
|
memcpy(state->n, n.data(), crypto_stream_chacha20_NONCEBYTES);
|
|
memcpy(state->k, k.data(), crypto_stream_chacha20_KEYBYTES);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_xor_wrap_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
|
|
auto *next_block = state->next_block;
|
|
|
|
size_t m_size = m.size_bytes();
|
|
auto *c_ptr = c.data();
|
|
auto *m_ptr = m.data();
|
|
|
|
if (state->remainder) {
|
|
uint64_t offset = 0;
|
|
int rem = state->remainder;
|
|
|
|
while (rem < 64 && offset < m_size) {
|
|
c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
|
|
offset++;
|
|
rem++;
|
|
}
|
|
|
|
c_ptr += offset;
|
|
m_ptr += offset;
|
|
m_size -= offset;
|
|
state->remainder = (rem == 64) ? 0 : rem;
|
|
|
|
if (m_size == 0) return;
|
|
}
|
|
|
|
state->remainder = m_size & 63;
|
|
size_t main_len = m_size - state->remainder;
|
|
|
|
crypto_stream_chacha20_xor_ic(
|
|
c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
|
|
);
|
|
|
|
state->block_counter += main_len / 64;
|
|
|
|
if (state->remainder) {
|
|
sodium_memzero(next_block + state->remainder, 64 - state->remainder);
|
|
memcpy(next_block, m_ptr + main_len, state->remainder);
|
|
|
|
crypto_stream_chacha20_xor_ic(
|
|
next_block, next_block, 64, state->n, state->block_counter, state->k
|
|
);
|
|
memcpy(c_ptr + main_len, next_block, state->remainder);
|
|
|
|
state->block_counter++;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_xor_wrap_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_xor_state, 1> state
|
|
) {
|
|
sodium_memzero(state->n, sizeof(state->n));
|
|
sodium_memzero(state->k, sizeof(state->k));
|
|
sodium_memzero(state->next_block, sizeof(state->next_block));
|
|
state->remainder = 0;
|
|
}
|
|
|
|
struct sn_crypto_stream_chacha20_ietf_xor_state {
|
|
unsigned char n[crypto_stream_chacha20_ietf_NONCEBYTES];
|
|
unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
|
|
unsigned char next_block[64];
|
|
int remainder;
|
|
uint64_t block_counter;
|
|
};
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_ietf_xor_wrap_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_chacha20_ietf_KEYBYTES);
|
|
|
|
state->remainder = 0;
|
|
state->block_counter = 0;
|
|
memcpy(state->n, n.data(), crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
memcpy(state->k, k.data(), crypto_stream_chacha20_ietf_KEYBYTES);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_ietf_xor_wrap_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
|
|
auto *next_block = state->next_block;
|
|
|
|
size_t m_size = m.size_bytes();
|
|
auto *c_ptr = c.data();
|
|
auto *m_ptr = m.data();
|
|
|
|
if (state->remainder) {
|
|
uint64_t offset = 0;
|
|
int rem = state->remainder;
|
|
|
|
while (rem < 64 && offset < m_size) {
|
|
c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
|
|
offset++;
|
|
rem++;
|
|
}
|
|
|
|
c_ptr += offset;
|
|
m_ptr += offset;
|
|
m_size -= offset;
|
|
state->remainder = (rem == 64) ? 0 : rem;
|
|
|
|
if (m_size == 0) return;
|
|
}
|
|
|
|
state->remainder = m_size & 63;
|
|
size_t main_len = m_size - state->remainder;
|
|
|
|
crypto_stream_chacha20_ietf_xor_ic(
|
|
c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
|
|
);
|
|
|
|
state->block_counter += main_len / 64;
|
|
|
|
if (state->remainder) {
|
|
sodium_memzero(next_block + state->remainder, 64 - state->remainder);
|
|
memcpy(next_block, m_ptr + main_len, state->remainder);
|
|
|
|
crypto_stream_chacha20_ietf_xor_ic(
|
|
next_block, next_block, 64, state->n, state->block_counter, state->k
|
|
);
|
|
memcpy(c_ptr + main_len, next_block, state->remainder);
|
|
|
|
state->block_counter++;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_chacha20_ietf_xor_wrap_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_chacha20_ietf_xor_state, 1> state
|
|
) {
|
|
sodium_memzero(state->n, sizeof(state->n));
|
|
sodium_memzero(state->k, sizeof(state->k));
|
|
sodium_memzero(state->next_block, sizeof(state->next_block));
|
|
state->remainder = 0;
|
|
}
|
|
|
|
struct sn_crypto_stream_xchacha20_xor_state {
|
|
unsigned char n[crypto_stream_xchacha20_NONCEBYTES];
|
|
unsigned char k[crypto_stream_xchacha20_KEYBYTES];
|
|
unsigned char next_block[64];
|
|
int remainder;
|
|
uint64_t block_counter;
|
|
};
|
|
|
|
static inline void
|
|
sn_crypto_stream_xchacha20_xor_wrap_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_xchacha20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_xchacha20_KEYBYTES);
|
|
|
|
state->remainder = 0;
|
|
state->block_counter = 0;
|
|
memcpy(state->n, n.data(), crypto_stream_xchacha20_NONCEBYTES);
|
|
memcpy(state->k, k.data(), crypto_stream_xchacha20_KEYBYTES);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_xchacha20_xor_wrap_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
|
|
auto *next_block = state->next_block;
|
|
|
|
size_t m_size = m.size_bytes();
|
|
auto *c_ptr = c.data();
|
|
auto *m_ptr = m.data();
|
|
|
|
if (state->remainder) {
|
|
uint64_t offset = 0;
|
|
int rem = state->remainder;
|
|
|
|
while (rem < 64 && offset < m_size) {
|
|
c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
|
|
++offset;
|
|
++rem;
|
|
}
|
|
|
|
c_ptr += offset;
|
|
m_ptr += offset;
|
|
m_size -= offset;
|
|
state->remainder = (rem == 64) ? 0 : rem;
|
|
|
|
if (m_size == 0) return;
|
|
}
|
|
|
|
state->remainder = m_size & 63;
|
|
size_t main_len = m_size - state->remainder;
|
|
|
|
crypto_stream_xchacha20_xor_ic(
|
|
c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
|
|
);
|
|
|
|
state->block_counter += main_len / 64;
|
|
|
|
if (state->remainder) {
|
|
sodium_memzero(next_block + state->remainder, 64 - state->remainder);
|
|
memcpy(next_block, m_ptr + main_len, state->remainder);
|
|
|
|
crypto_stream_xchacha20_xor_ic(
|
|
next_block, next_block, 64, state->n, state->block_counter, state->k
|
|
);
|
|
memcpy(c_ptr + main_len, next_block, state->remainder);
|
|
|
|
state->block_counter++;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_xchacha20_xor_wrap_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_xchacha20_xor_state, 1> state
|
|
) {
|
|
sodium_memzero(state->n, sizeof(state->n));
|
|
sodium_memzero(state->k, sizeof(state->k));
|
|
sodium_memzero(state->next_block, sizeof(state->next_block));
|
|
state->remainder = 0;
|
|
}
|
|
|
|
struct sn_crypto_stream_salsa20_xor_state {
|
|
unsigned char n[crypto_stream_salsa20_NONCEBYTES];
|
|
unsigned char k[crypto_stream_salsa20_KEYBYTES];
|
|
unsigned char next_block[64];
|
|
int remainder;
|
|
uint64_t block_counter;
|
|
};
|
|
|
|
static inline void
|
|
sn_crypto_stream_salsa20_xor_wrap_init(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> k
|
|
) {
|
|
assert(n.size_bytes() == crypto_stream_salsa20_NONCEBYTES);
|
|
assert(k.size_bytes() == crypto_stream_salsa20_KEYBYTES);
|
|
|
|
state->remainder = 0;
|
|
state->block_counter = 0;
|
|
memcpy(state->n, n.data(), crypto_stream_salsa20_NONCEBYTES);
|
|
memcpy(state->k, k.data(), crypto_stream_salsa20_KEYBYTES);
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_salsa20_xor_wrap_update(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state,
|
|
js_typedarray_span_t<> c,
|
|
js_typedarray_span_t<> m
|
|
) {
|
|
assert(c.size_bytes() == m.size_bytes());
|
|
|
|
auto *next_block = state->next_block;
|
|
|
|
size_t m_size = m.size_bytes();
|
|
auto *c_ptr = c.data();
|
|
auto *m_ptr = m.data();
|
|
|
|
if (state->remainder) {
|
|
uint64_t offset = 0;
|
|
int rem = state->remainder;
|
|
|
|
while (rem < 64 && offset < m_size) {
|
|
c_ptr[offset] = next_block[rem] ^ m_ptr[offset];
|
|
++offset;
|
|
++rem;
|
|
}
|
|
|
|
c_ptr += offset;
|
|
m_ptr += offset;
|
|
m_size -= offset;
|
|
state->remainder = (rem == 64) ? 0 : rem;
|
|
|
|
if (m_size == 0) return;
|
|
}
|
|
|
|
state->remainder = m_size & 63;
|
|
size_t main_len = m_size - state->remainder;
|
|
|
|
crypto_stream_salsa20_xor_ic(
|
|
c_ptr, m_ptr, main_len, state->n, state->block_counter, state->k
|
|
);
|
|
|
|
state->block_counter += main_len / 64;
|
|
|
|
if (state->remainder) {
|
|
sodium_memzero(next_block + state->remainder, 64 - state->remainder);
|
|
memcpy(next_block, m_ptr + main_len, state->remainder);
|
|
|
|
crypto_stream_salsa20_xor_ic(
|
|
next_block, next_block, 64, state->n, state->block_counter, state->k
|
|
);
|
|
memcpy(c_ptr + main_len, next_block, state->remainder);
|
|
|
|
state->block_counter++;
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
sn_crypto_stream_salsa20_xor_wrap_final(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_of_t<sn_crypto_stream_salsa20_xor_state, 1> state
|
|
) {
|
|
sodium_memzero(state->n, sizeof(state->n));
|
|
sodium_memzero(state->k, sizeof(state->k));
|
|
sodium_memzero(state->next_block, sizeof(state->next_block));
|
|
state->remainder = 0;
|
|
}
|
|
|
|
// Experimental API
|
|
|
|
static inline void
|
|
sn_extension_tweak_ed25519_base(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> p,
|
|
js_typedarray_span_t<> ns
|
|
) {
|
|
assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(p.size_bytes() == sn__extension_tweak_ed25519_BYTES);
|
|
|
|
sn__extension_tweak_ed25519_base(p.data(), n.data(), ns.data(), ns.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_extension_tweak_ed25519_sign_detached(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> sig,
|
|
js_typedarray_span_t<> m,
|
|
js_typedarray_span_t<> scalar,
|
|
std::optional<js_typedarray_span_t<>> pk
|
|
) {
|
|
assert(sig.size_bytes() == crypto_sign_BYTES);
|
|
assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
uint8_t *pk_data = nullptr;
|
|
if (pk) {
|
|
assert(pk->size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
pk_data = pk->data();
|
|
}
|
|
|
|
return sn__extension_tweak_ed25519_sign_detached(
|
|
sig.data(),
|
|
nullptr,
|
|
m.data(),
|
|
m.size_bytes(),
|
|
scalar.data(),
|
|
pk_data
|
|
);
|
|
}
|
|
|
|
static inline void
|
|
sn_extension_tweak_ed25519_sk_to_scalar(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> n,
|
|
js_typedarray_span_t<> sk
|
|
) {
|
|
assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(sk.size_bytes() == crypto_sign_SECRETKEYBYTES);
|
|
|
|
sn__extension_tweak_ed25519_sk_to_scalar(n.data(), sk.data());
|
|
}
|
|
|
|
static inline void
|
|
sn_extension_tweak_ed25519_scalar(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> scalar_out,
|
|
js_typedarray_span_t<> scalar,
|
|
js_typedarray_span_t<> ns
|
|
) {
|
|
assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
sn__extension_tweak_ed25519_scalar(scalar_out.data(), scalar.data(), ns.data(), ns.size_bytes());
|
|
}
|
|
|
|
static inline int
|
|
sn_extension_tweak_ed25519_pk(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> tpk,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> ns
|
|
) {
|
|
assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
|
|
return sn__extension_tweak_ed25519_pk(tpk.data(), pk.data(), ns.data(), ns.size_bytes());
|
|
}
|
|
|
|
static inline void
|
|
sn_extension_tweak_ed25519_keypair(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> scalar_out,
|
|
js_typedarray_span_t<> scalar_in,
|
|
js_typedarray_span_t<> ns
|
|
) {
|
|
assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
|
|
assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
sn__extension_tweak_ed25519_keypair(
|
|
pk.data(),
|
|
scalar_out.data(),
|
|
scalar_in.data(),
|
|
ns.data(),
|
|
ns.size_bytes()
|
|
);
|
|
}
|
|
|
|
static inline void
|
|
sn_extension_tweak_ed25519_scalar_add(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> scalar_out,
|
|
js_typedarray_span_t<> scalar,
|
|
js_typedarray_span_t<> n
|
|
) {
|
|
assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(scalar.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(n.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
sn__extension_tweak_ed25519_scalar_add(scalar_out.data(), scalar.data(), n.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_extension_tweak_ed25519_pk_add(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> tpk,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> p
|
|
) {
|
|
assert(tpk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(pk.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
assert(p.size_bytes() == crypto_sign_PUBLICKEYBYTES);
|
|
|
|
return sn__extension_tweak_ed25519_pk_add(tpk.data(), pk.data(), p.data());
|
|
}
|
|
|
|
static inline int
|
|
sn_extension_tweak_ed25519_keypair_add(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> pk,
|
|
js_typedarray_span_t<> scalar_out,
|
|
js_typedarray_span_t<> scalar_in,
|
|
js_typedarray_span_t<> tweak
|
|
) {
|
|
assert(pk.size_bytes() == sn__extension_tweak_ed25519_BYTES);
|
|
assert(scalar_out.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(scalar_in.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
assert(tweak.size_bytes() == sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
return sn__extension_tweak_ed25519_keypair_add(
|
|
pk.data(),
|
|
scalar_out.data(),
|
|
scalar_in.data(),
|
|
tweak.data()
|
|
);
|
|
}
|
|
|
|
static inline int
|
|
sn_extension_pbkdf2_sha512(
|
|
js_env_t *,
|
|
js_receiver_t,
|
|
js_typedarray_span_t<> out,
|
|
js_typedarray_span_t<> passwd,
|
|
js_typedarray_span_t<> salt,
|
|
uint64_t iter,
|
|
uint64_t outlen
|
|
) {
|
|
|
|
assert(iter >= sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
|
|
assert(outlen <= sn__extension_pbkdf2_sha512_BYTES_MAX);
|
|
assert(out.size_bytes() >= static_cast<size_t>(outlen));
|
|
|
|
return sn__extension_pbkdf2_sha512(
|
|
passwd.data(),
|
|
passwd.size_bytes(),
|
|
salt.data(),
|
|
salt.size_bytes(),
|
|
iter,
|
|
out.data(),
|
|
outlen
|
|
);
|
|
}
|
|
|
|
struct sn_async_pbkdf2_sha512_request : sn_async_task {
|
|
js_persistent_t<js_arraybuffer_t> out_ref;
|
|
std::span<uint8_t> out;
|
|
|
|
size_t outlen;
|
|
|
|
js_persistent_t<js_arraybuffer_t> pwd_ref;
|
|
std::span<uint8_t> pwd;
|
|
|
|
js_persistent_t<js_arraybuffer_t> salt_ref;
|
|
std::span<uint8_t> salt;
|
|
|
|
uint64_t iter;
|
|
|
|
sn_async_pbkdf2_sha512_request(js_env_t *env) : sn_async_task(env) {}
|
|
};
|
|
|
|
static void
|
|
async_pbkdf2_sha512_execute(uv_work_t *uv_req) {
|
|
auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
|
|
|
|
req->code = sn__extension_pbkdf2_sha512(
|
|
req->pwd.data(),
|
|
req->pwd.size(),
|
|
req->salt.data(),
|
|
req->salt.size(),
|
|
req->iter,
|
|
req->out.data(),
|
|
req->outlen
|
|
);
|
|
}
|
|
|
|
static void
|
|
async_pbkdf2_sha512_complete(uv_work_t *uv_req, int status) {
|
|
int err;
|
|
|
|
auto *req = reinterpret_cast<sn_async_pbkdf2_sha512_request *>(uv_req);
|
|
|
|
if (req->exiting) return delete req;
|
|
|
|
js_handle_scope_t *scope;
|
|
err = js_open_handle_scope(req->env, &scope);
|
|
assert(err == 0);
|
|
|
|
js_function_t<void, int> callback;
|
|
err = js_get_reference_value(req->env, req->cb, callback);
|
|
assert(err == 0);
|
|
|
|
err = js_call_function_with_checkpoint(req->env, callback, req->code);
|
|
assert(err != js_pending_exception);
|
|
|
|
err = js_close_handle_scope(req->env, scope);
|
|
assert(err == 0);
|
|
|
|
delete req;
|
|
}
|
|
|
|
static inline void
|
|
sn_extension_pbkdf2_sha512_async(
|
|
js_env_t *env,
|
|
js_receiver_t,
|
|
|
|
js_arraybuffer_t out,
|
|
uint32_t out_offset,
|
|
uint32_t out_len,
|
|
|
|
js_arraybuffer_t pwd,
|
|
uint32_t pwd_offset,
|
|
uint32_t pwd_len,
|
|
|
|
js_arraybuffer_t salt,
|
|
uint32_t salt_offset,
|
|
uint32_t salt_len,
|
|
|
|
uint64_t iter,
|
|
uint64_t outlen,
|
|
|
|
js_function_t<void, int> callback
|
|
) {
|
|
int err;
|
|
|
|
auto *req = new sn_async_pbkdf2_sha512_request(env);
|
|
|
|
std::span<uint8_t> out_view;
|
|
err = js_get_arraybuffer_info(env, out, out_view);
|
|
assert(err == 0);
|
|
assert(out_offset + out_len <= out_view.size());
|
|
|
|
req->out = {&out_view[out_offset], out_len};
|
|
|
|
std::span<uint8_t> pwd_view;
|
|
err = js_get_arraybuffer_info(env, pwd, pwd_view);
|
|
assert(err == 0);
|
|
assert(pwd_offset + pwd_len <= pwd_view.size());
|
|
|
|
req->pwd = {&pwd_view[pwd_offset], pwd_len};
|
|
|
|
std::span<uint8_t> salt_view;
|
|
err = js_get_arraybuffer_info(env, salt, salt_view);
|
|
assert(err == 0);
|
|
assert(salt_offset + salt_len <= salt_view.size());
|
|
|
|
req->salt = {&salt_view[salt_offset], salt_len};
|
|
|
|
req->iter = iter;
|
|
req->outlen = outlen;
|
|
|
|
err = js_create_reference(env, out, req->out_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, pwd, req->pwd_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, salt, req->salt_ref);
|
|
assert(err == 0);
|
|
|
|
err = js_create_reference(env, callback, req->cb);
|
|
assert(err == 0);
|
|
|
|
uv_loop_t *loop;
|
|
err = js_get_env_loop(env, &loop);
|
|
assert(err == 0);
|
|
|
|
err = uv_queue_work(loop, &req->task, async_pbkdf2_sha512_execute, async_pbkdf2_sha512_complete);
|
|
assert(err == 0);
|
|
}
|
|
|
|
static js_value_t *
|
|
sodium_native_exports(js_env_t *env, js_value_t *exports) {
|
|
int err;
|
|
|
|
err = sodium_init();
|
|
assert(err >= 0);
|
|
|
|
#define V_FUNCTION(name, fn) \
|
|
err = js_set_property<fn>(env, exports, name); \
|
|
assert(err == 0);
|
|
|
|
#define V_FUNCTION_NOSCOPE(name, fn) \
|
|
err = js_set_property<fn, js_function_options_t{.scoped = false}>(env, exports, name); \
|
|
assert(err == 0);
|
|
|
|
#define V_UINT32(name, constant) \
|
|
err = js_set_property(env, exports, name, static_cast<uint32_t>(constant)); \
|
|
assert(err == 0);
|
|
|
|
#define V_UINT64(name, constant) \
|
|
err = js_set_property(env, exports, name, static_cast<int64_t>(std::min<uint64_t>(constant, js_max_safe_integer))); \
|
|
assert(err == 0);
|
|
|
|
#define V_STRING(name, str) \
|
|
err = js_set_property(env, exports, name, str); \
|
|
assert(err == 0);
|
|
|
|
// memory
|
|
|
|
V_FUNCTION("sodium_memzero", sn_sodium_memzero);
|
|
V_FUNCTION("sodium_mlock", sn_sodium_mlock);
|
|
V_FUNCTION("sodium_munlock", sn_sodium_munlock);
|
|
V_FUNCTION("sodium_malloc", sn_sodium_malloc);
|
|
V_FUNCTION("sodium_free", sn_sodium_free);
|
|
V_FUNCTION("sodium_mprotect_noaccess", sn_sodium_mprotect_noaccess);
|
|
V_FUNCTION("sodium_mprotect_readonly", sn_sodium_mprotect_readonly);
|
|
V_FUNCTION("sodium_mprotect_readwrite", sn_sodium_mprotect_readwrite);
|
|
|
|
// randombytes
|
|
|
|
V_FUNCTION_NOSCOPE("randombytes_buf", sn_randombytes_buf);
|
|
V_FUNCTION_NOSCOPE("randombytes_buf_deterministic", sn_randombytes_buf_deterministic);
|
|
V_FUNCTION_NOSCOPE("randombytes_random", sn_randombytes_random);
|
|
V_FUNCTION_NOSCOPE("randombytes_uniform", sn_randombytes_uniform);
|
|
|
|
V_UINT32("randombytes_SEEDBYTES", randombytes_SEEDBYTES);
|
|
|
|
// sodium helpers
|
|
|
|
V_FUNCTION("sodium_memcmp", sn_sodium_memcmp);
|
|
V_FUNCTION("sodium_increment", sn_sodium_increment);
|
|
V_FUNCTION("sodium_add", sn_sodium_add);
|
|
V_FUNCTION("sodium_sub", sn_sodium_sub);
|
|
V_FUNCTION("sodium_compare", sn_sodium_compare);
|
|
V_FUNCTION("sodium_is_zero", sn_sodium_is_zero);
|
|
V_FUNCTION("sodium_pad", sn_sodium_pad);
|
|
V_FUNCTION("sodium_unpad", sn_sodium_unpad);
|
|
|
|
// crypto_aead
|
|
|
|
V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_keygen", sn_crypto_aead_xchacha20poly1305_ietf_keygen);
|
|
V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt", sn_crypto_aead_xchacha20poly1305_ietf_encrypt);
|
|
V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt", sn_crypto_aead_xchacha20poly1305_ietf_decrypt);
|
|
V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_encrypt_detached);
|
|
V_FUNCTION("crypto_aead_xchacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_xchacha20poly1305_ietf_decrypt_detached);
|
|
V_UINT32("crypto_aead_xchacha20poly1305_ietf_ABYTES", crypto_aead_xchacha20poly1305_ietf_ABYTES);
|
|
V_UINT32("crypto_aead_xchacha20poly1305_ietf_KEYBYTES", crypto_aead_xchacha20poly1305_ietf_KEYBYTES);
|
|
V_UINT32("crypto_aead_xchacha20poly1305_ietf_NPUBBYTES", crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
V_UINT32("crypto_aead_xchacha20poly1305_ietf_NSECBYTES", crypto_aead_xchacha20poly1305_ietf_NSECBYTES);
|
|
V_UINT64("crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX);
|
|
|
|
V_FUNCTION("crypto_aead_chacha20poly1305_ietf_keygen", sn_crypto_aead_chacha20poly1305_ietf_keygen);
|
|
V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt", sn_crypto_aead_chacha20poly1305_ietf_encrypt);
|
|
V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt", sn_crypto_aead_chacha20poly1305_ietf_decrypt);
|
|
V_FUNCTION("crypto_aead_chacha20poly1305_ietf_encrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_encrypt_detached);
|
|
V_FUNCTION("crypto_aead_chacha20poly1305_ietf_decrypt_detached", sn_crypto_aead_chacha20poly1305_ietf_decrypt_detached);
|
|
V_UINT32("crypto_aead_chacha20poly1305_ietf_ABYTES", crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
V_UINT32("crypto_aead_chacha20poly1305_ietf_KEYBYTES", crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
V_UINT32("crypto_aead_chacha20poly1305_ietf_NPUBBYTES", crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
V_UINT32("crypto_aead_chacha20poly1305_ietf_NSECBYTES", crypto_aead_chacha20poly1305_ietf_NSECBYTES);
|
|
V_UINT64("crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX", crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
|
|
|
|
// crypto_auth
|
|
|
|
V_FUNCTION("crypto_auth", sn_crypto_auth);
|
|
V_FUNCTION("crypto_auth_verify", sn_crypto_auth_verify);
|
|
V_UINT32("crypto_auth_BYTES", crypto_auth_BYTES);
|
|
V_UINT32("crypto_auth_KEYBYTES", crypto_auth_KEYBYTES);
|
|
V_STRING("crypto_auth_PRIMITIVE", crypto_auth_PRIMITIVE);
|
|
|
|
// crypto_box
|
|
|
|
V_FUNCTION("crypto_box_keypair", sn_crypto_box_keypair);
|
|
V_FUNCTION("crypto_box_seed_keypair", sn_crypto_box_seed_keypair);
|
|
V_FUNCTION("crypto_box_easy", sn_crypto_box_easy);
|
|
V_FUNCTION("crypto_box_open_easy", sn_crypto_box_open_easy);
|
|
V_FUNCTION("crypto_box_detached", sn_crypto_box_detached);
|
|
V_FUNCTION("crypto_box_open_detached", sn_crypto_box_open_detached);
|
|
V_FUNCTION("crypto_box_seal", sn_crypto_box_seal);
|
|
V_FUNCTION_NOSCOPE("crypto_box_seal_open", sn_crypto_box_seal_open);
|
|
|
|
V_UINT32("crypto_box_SEEDBYTES", crypto_box_SEEDBYTES);
|
|
V_UINT32("crypto_box_PUBLICKEYBYTES", crypto_box_PUBLICKEYBYTES);
|
|
V_UINT32("crypto_box_SECRETKEYBYTES", crypto_box_SECRETKEYBYTES);
|
|
V_UINT32("crypto_box_NONCEBYTES", crypto_box_NONCEBYTES);
|
|
V_UINT32("crypto_box_MACBYTES", crypto_box_MACBYTES);
|
|
V_UINT32("crypto_box_SEALBYTES", crypto_box_SEALBYTES);
|
|
V_STRING("crypto_box_PRIMITIVE", crypto_box_PRIMITIVE);
|
|
|
|
// crypto_core
|
|
|
|
V_FUNCTION("crypto_core_ed25519_is_valid_point", sn_crypto_core_ed25519_is_valid_point);
|
|
V_FUNCTION("crypto_core_ed25519_from_uniform", sn_crypto_core_ed25519_from_uniform);
|
|
V_FUNCTION("crypto_core_ed25519_add", sn_crypto_core_ed25519_add);
|
|
V_FUNCTION("crypto_core_ed25519_sub", sn_crypto_core_ed25519_sub);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_random", sn_crypto_core_ed25519_scalar_random);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_reduce", sn_crypto_core_ed25519_scalar_reduce);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_invert", sn_crypto_core_ed25519_scalar_invert);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_negate", sn_crypto_core_ed25519_scalar_negate);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_complement", sn_crypto_core_ed25519_scalar_complement);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_add", sn_crypto_core_ed25519_scalar_add);
|
|
V_FUNCTION("crypto_core_ed25519_scalar_sub", sn_crypto_core_ed25519_scalar_sub);
|
|
V_UINT32("crypto_core_ed25519_BYTES", crypto_core_ed25519_BYTES);
|
|
V_UINT32("crypto_core_ed25519_UNIFORMBYTES", crypto_core_ed25519_UNIFORMBYTES);
|
|
V_UINT32("crypto_core_ed25519_SCALARBYTES", crypto_core_ed25519_SCALARBYTES);
|
|
V_UINT32("crypto_core_ed25519_NONREDUCEDSCALARBYTES", crypto_core_ed25519_NONREDUCEDSCALARBYTES);
|
|
|
|
// crypto_kdf
|
|
|
|
V_FUNCTION("crypto_kdf_keygen", sn_crypto_kdf_keygen);
|
|
V_FUNCTION("crypto_kdf_derive_from_key", sn_crypto_kdf_derive_from_key);
|
|
V_UINT32("crypto_kdf_BYTES_MIN", crypto_kdf_BYTES_MIN);
|
|
V_UINT32("crypto_kdf_BYTES_MAX", crypto_kdf_BYTES_MAX);
|
|
V_UINT32("crypto_kdf_CONTEXTBYTES", crypto_kdf_CONTEXTBYTES);
|
|
V_UINT32("crypto_kdf_KEYBYTES", crypto_kdf_KEYBYTES);
|
|
V_STRING("crypto_kdf_PRIMITIVE", crypto_kdf_PRIMITIVE);
|
|
|
|
// crypto_kx
|
|
|
|
V_FUNCTION("crypto_kx_keypair", sn_crypto_kx_keypair);
|
|
V_FUNCTION("crypto_kx_seed_keypair", sn_crypto_kx_seed_keypair);
|
|
V_FUNCTION("crypto_kx_client_session_keys", sn_crypto_kx_client_session_keys);
|
|
V_FUNCTION("crypto_kx_server_session_keys", sn_crypto_kx_server_session_keys);
|
|
V_UINT32("crypto_kx_PUBLICKEYBYTES", crypto_kx_PUBLICKEYBYTES);
|
|
V_UINT32("crypto_kx_SECRETKEYBYTES", crypto_kx_SECRETKEYBYTES);
|
|
V_UINT32("crypto_kx_SEEDBYTES", crypto_kx_SEEDBYTES);
|
|
V_UINT32("crypto_kx_SESSIONKEYBYTES", crypto_kx_SESSIONKEYBYTES);
|
|
V_STRING("crypto_kx_PRIMITIVE", crypto_kx_PRIMITIVE);
|
|
|
|
// crypto_generichash
|
|
|
|
V_FUNCTION_NOSCOPE("crypto_generichash", sn_crypto_generichash);
|
|
V_FUNCTION("crypto_generichash_batch", sn_crypto_generichash_batch);
|
|
V_FUNCTION_NOSCOPE("crypto_generichash_keygen", sn_crypto_generichash_keygen);
|
|
V_FUNCTION_NOSCOPE("crypto_generichash_init", sn_crypto_generichash_init);
|
|
V_FUNCTION_NOSCOPE("crypto_generichash_update", sn_crypto_generichash_update);
|
|
V_FUNCTION_NOSCOPE("crypto_generichash_final", sn_crypto_generichash_final);
|
|
|
|
V_UINT32("crypto_generichash_STATEBYTES", sizeof(crypto_generichash_state));
|
|
V_STRING("crypto_generichash_PRIMITIVE", crypto_generichash_PRIMITIVE);
|
|
V_UINT32("crypto_generichash_BYTES_MIN", crypto_generichash_BYTES_MIN);
|
|
V_UINT32("crypto_generichash_BYTES_MAX", crypto_generichash_BYTES_MAX);
|
|
V_UINT32("crypto_generichash_BYTES", crypto_generichash_BYTES);
|
|
V_UINT32("crypto_generichash_KEYBYTES_MIN", crypto_generichash_KEYBYTES_MIN);
|
|
V_UINT32("crypto_generichash_KEYBYTES_MAX", crypto_generichash_KEYBYTES_MAX);
|
|
V_UINT32("crypto_generichash_KEYBYTES", crypto_generichash_KEYBYTES);
|
|
|
|
// crypto_hash
|
|
|
|
V_FUNCTION("crypto_hash", sn_crypto_hash);
|
|
V_UINT32("crypto_hash_BYTES", crypto_hash_BYTES);
|
|
V_STRING("crypto_hash_PRIMITIVE", crypto_hash_PRIMITIVE);
|
|
|
|
V_FUNCTION("crypto_hash_sha256", sn_crypto_hash_sha256);
|
|
V_FUNCTION("crypto_hash_sha256_init", sn_crypto_hash_sha256_init);
|
|
V_FUNCTION("crypto_hash_sha256_update", sn_crypto_hash_sha256_update);
|
|
V_FUNCTION("crypto_hash_sha256_final", sn_crypto_hash_sha256_final);
|
|
V_UINT32("crypto_hash_sha256_STATEBYTES", sizeof(crypto_hash_sha256_state));
|
|
V_UINT32("crypto_hash_sha256_BYTES", crypto_hash_sha256_BYTES);
|
|
|
|
V_FUNCTION("crypto_hash_sha512", sn_crypto_hash_sha512);
|
|
V_FUNCTION("crypto_hash_sha512_init", sn_crypto_hash_sha512_init);
|
|
V_FUNCTION("crypto_hash_sha512_update", sn_crypto_hash_sha512_update);
|
|
V_FUNCTION("crypto_hash_sha512_final", sn_crypto_hash_sha512_final);
|
|
V_UINT32("crypto_hash_sha512_STATEBYTES", sizeof(crypto_hash_sha512_state));
|
|
V_UINT32("crypto_hash_sha512_BYTES", crypto_hash_sha512_BYTES);
|
|
|
|
// crypto_onetimeauth
|
|
|
|
V_FUNCTION("crypto_onetimeauth", sn_crypto_onetimeauth);
|
|
V_FUNCTION("crypto_onetimeauth_verify", sn_crypto_onetimeauth_verify);
|
|
V_FUNCTION("crypto_onetimeauth_init", sn_crypto_onetimeauth_init);
|
|
V_FUNCTION("crypto_onetimeauth_update", sn_crypto_onetimeauth_update);
|
|
V_FUNCTION("crypto_onetimeauth_final", sn_crypto_onetimeauth_final);
|
|
V_UINT32("crypto_onetimeauth_STATEBYTES", sizeof(crypto_onetimeauth_state));
|
|
V_UINT32("crypto_onetimeauth_BYTES", crypto_onetimeauth_BYTES);
|
|
V_UINT32("crypto_onetimeauth_KEYBYTES", crypto_onetimeauth_KEYBYTES);
|
|
V_STRING("crypto_onetimeauth_PRIMITIVE", crypto_onetimeauth_PRIMITIVE);
|
|
|
|
// crypto_pwhash
|
|
|
|
V_FUNCTION("crypto_pwhash", sn_crypto_pwhash);
|
|
V_FUNCTION("crypto_pwhash_str", sn_crypto_pwhash_str);
|
|
V_FUNCTION("crypto_pwhash_str_verify", sn_crypto_pwhash_str_verify);
|
|
V_FUNCTION("crypto_pwhash_str_needs_rehash", sn_crypto_pwhash_str_needs_rehash);
|
|
V_FUNCTION("crypto_pwhash_async", sn_crypto_pwhash_async);
|
|
V_FUNCTION("crypto_pwhash_str_async", sn_crypto_pwhash_str_async);
|
|
V_FUNCTION("crypto_pwhash_str_verify_async", sn_crypto_pwhash_str_verify_async);
|
|
V_UINT32("crypto_pwhash_ALG_ARGON2I13", crypto_pwhash_ALG_ARGON2I13);
|
|
V_UINT32("crypto_pwhash_ALG_ARGON2ID13", crypto_pwhash_ALG_ARGON2ID13);
|
|
V_UINT32("crypto_pwhash_ALG_DEFAULT", crypto_pwhash_ALG_DEFAULT);
|
|
V_UINT32("crypto_pwhash_BYTES_MIN", crypto_pwhash_BYTES_MIN);
|
|
V_UINT32("crypto_pwhash_BYTES_MAX", crypto_pwhash_BYTES_MAX);
|
|
V_UINT32("crypto_pwhash_PASSWD_MIN", crypto_pwhash_PASSWD_MIN);
|
|
V_UINT32("crypto_pwhash_PASSWD_MAX", crypto_pwhash_PASSWD_MAX);
|
|
V_UINT32("crypto_pwhash_SALTBYTES", crypto_pwhash_SALTBYTES);
|
|
V_UINT32("crypto_pwhash_STRBYTES", crypto_pwhash_STRBYTES);
|
|
V_STRING("crypto_pwhash_STRPREFIX", crypto_pwhash_STRPREFIX);
|
|
V_UINT32("crypto_pwhash_OPSLIMIT_MIN", crypto_pwhash_OPSLIMIT_MIN);
|
|
V_UINT32("crypto_pwhash_OPSLIMIT_MAX", crypto_pwhash_OPSLIMIT_MAX);
|
|
V_UINT64("crypto_pwhash_MEMLIMIT_MIN", crypto_pwhash_MEMLIMIT_MIN);
|
|
V_UINT64("crypto_pwhash_MEMLIMIT_MAX", crypto_pwhash_MEMLIMIT_MAX);
|
|
V_UINT32("crypto_pwhash_OPSLIMIT_INTERACTIVE", crypto_pwhash_OPSLIMIT_INTERACTIVE);
|
|
V_UINT64("crypto_pwhash_MEMLIMIT_INTERACTIVE", crypto_pwhash_MEMLIMIT_INTERACTIVE);
|
|
V_UINT32("crypto_pwhash_OPSLIMIT_MODERATE", crypto_pwhash_OPSLIMIT_MODERATE);
|
|
V_UINT64("crypto_pwhash_MEMLIMIT_MODERATE", crypto_pwhash_MEMLIMIT_MODERATE);
|
|
V_UINT32("crypto_pwhash_OPSLIMIT_SENSITIVE", crypto_pwhash_OPSLIMIT_SENSITIVE);
|
|
V_UINT64("crypto_pwhash_MEMLIMIT_SENSITIVE", crypto_pwhash_MEMLIMIT_SENSITIVE);
|
|
V_STRING("crypto_pwhash_PRIMITIVE", crypto_pwhash_PRIMITIVE);
|
|
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256", sn_crypto_pwhash_scryptsalsa208sha256);
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str", sn_crypto_pwhash_scryptsalsa208sha256_str);
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify", sn_crypto_pwhash_scryptsalsa208sha256_str_verify);
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_needs_rehash", sn_crypto_pwhash_scryptsalsa208sha256_str_needs_rehash);
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_async", sn_crypto_pwhash_scryptsalsa208sha256_async);
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_async", sn_crypto_pwhash_scryptsalsa208sha256_str_async)
|
|
V_FUNCTION("crypto_pwhash_scryptsalsa208sha256_str_verify_async", sn_crypto_pwhash_scryptsalsa208sha256_str_verify_async);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MIN", crypto_pwhash_scryptsalsa208sha256_BYTES_MIN);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_BYTES_MAX", crypto_pwhash_scryptsalsa208sha256_BYTES_MAX);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN", crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX", crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_SALTBYTES", crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_STRBYTES", crypto_pwhash_scryptsalsa208sha256_STRBYTES);
|
|
V_STRING("crypto_pwhash_scryptsalsa208sha256_STRPREFIX", crypto_pwhash_scryptsalsa208sha256_STRPREFIX);
|
|
V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN);
|
|
V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX);
|
|
V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
|
|
V_UINT32("crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE);
|
|
V_UINT64("crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE", crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE);
|
|
|
|
// crypto_scalarmult
|
|
|
|
V_FUNCTION("crypto_scalarmult_base", sn_crypto_scalarmult_base);
|
|
V_FUNCTION("crypto_scalarmult", sn_crypto_scalarmult);
|
|
V_STRING("crypto_scalarmult_PRIMITIVE", crypto_scalarmult_PRIMITIVE);
|
|
V_UINT32("crypto_scalarmult_BYTES", crypto_scalarmult_BYTES);
|
|
V_UINT32("crypto_scalarmult_SCALARBYTES", crypto_scalarmult_SCALARBYTES);
|
|
|
|
V_FUNCTION("crypto_scalarmult_ed25519_base", sn_crypto_scalarmult_ed25519_base);
|
|
V_FUNCTION("crypto_scalarmult_ed25519", sn_crypto_scalarmult_ed25519);
|
|
V_FUNCTION("crypto_scalarmult_ed25519_base_noclamp", sn_crypto_scalarmult_ed25519_base_noclamp);
|
|
V_FUNCTION("crypto_scalarmult_ed25519_noclamp", sn_crypto_scalarmult_ed25519_noclamp);
|
|
V_UINT32("crypto_scalarmult_ed25519_BYTES", crypto_scalarmult_ed25519_BYTES);
|
|
V_UINT32("crypto_scalarmult_ed25519_SCALARBYTES", crypto_scalarmult_ed25519_SCALARBYTES);
|
|
|
|
// crypto_secretbox
|
|
|
|
V_FUNCTION("crypto_secretbox_easy", sn_crypto_secretbox_easy);
|
|
V_FUNCTION("crypto_secretbox_open_easy", sn_crypto_secretbox_open_easy);
|
|
V_FUNCTION("crypto_secretbox_detached", sn_crypto_secretbox_detached);
|
|
V_FUNCTION("crypto_secretbox_open_detached", sn_crypto_secretbox_open_detached);
|
|
V_UINT32("crypto_secretbox_KEYBYTES", crypto_secretbox_KEYBYTES);
|
|
V_UINT32("crypto_secretbox_NONCEBYTES", crypto_secretbox_NONCEBYTES);
|
|
V_UINT32("crypto_secretbox_MACBYTES", crypto_secretbox_MACBYTES);
|
|
V_STRING("crypto_secretbox_PRIMITIVE", crypto_secretbox_PRIMITIVE);
|
|
|
|
// crypto_secretstream
|
|
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_keygen", sn_crypto_secretstream_xchacha20poly1305_keygen);
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_push", sn_crypto_secretstream_xchacha20poly1305_init_push);
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_init_pull", sn_crypto_secretstream_xchacha20poly1305_init_pull);
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_push", sn_crypto_secretstream_xchacha20poly1305_push);
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_pull", sn_crypto_secretstream_xchacha20poly1305_pull);
|
|
V_FUNCTION_NOSCOPE("crypto_secretstream_xchacha20poly1305_rekey", sn_crypto_secretstream_xchacha20poly1305_rekey);
|
|
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_STATEBYTES", sizeof(crypto_secretstream_xchacha20poly1305_state));
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_ABYTES", crypto_secretstream_xchacha20poly1305_ABYTES);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_HEADERBYTES", crypto_secretstream_xchacha20poly1305_HEADERBYTES);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_KEYBYTES", crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_TAGBYTES", 1);
|
|
V_UINT64("crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX", crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_MESSAGE", crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_PUSH", crypto_secretstream_xchacha20poly1305_TAG_PUSH);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_REKEY", crypto_secretstream_xchacha20poly1305_TAG_REKEY);
|
|
V_UINT32("crypto_secretstream_xchacha20poly1305_TAG_FINAL", crypto_secretstream_xchacha20poly1305_TAG_FINAL);
|
|
|
|
// crypto_shorthash
|
|
|
|
V_FUNCTION("crypto_shorthash", sn_crypto_shorthash);
|
|
V_UINT32("crypto_shorthash_BYTES", crypto_shorthash_BYTES);
|
|
V_UINT32("crypto_shorthash_KEYBYTES", crypto_shorthash_KEYBYTES);
|
|
V_STRING("crypto_shorthash_PRIMITIVE", crypto_shorthash_PRIMITIVE);
|
|
|
|
// crypto_sign
|
|
|
|
V_FUNCTION("crypto_sign_keypair", sn_crypto_sign_keypair);
|
|
V_FUNCTION("crypto_sign_seed_keypair", sn_crypto_sign_seed_keypair);
|
|
V_FUNCTION("crypto_sign", sn_crypto_sign);
|
|
V_FUNCTION("crypto_sign_open", sn_crypto_sign_open);
|
|
V_FUNCTION("crypto_sign_detached", sn_crypto_sign_detached);
|
|
V_FUNCTION_NOSCOPE("crypto_sign_verify_detached", sn_crypto_sign_verify_detached);
|
|
V_FUNCTION("crypto_sign_ed25519_sk_to_pk", sn_crypto_sign_ed25519_sk_to_pk);
|
|
V_FUNCTION("crypto_sign_ed25519_pk_to_curve25519", sn_crypto_sign_ed25519_pk_to_curve25519);
|
|
V_FUNCTION("crypto_sign_ed25519_sk_to_curve25519", sn_crypto_sign_ed25519_sk_to_curve25519);
|
|
|
|
V_UINT32("crypto_sign_SEEDBYTES", crypto_sign_SEEDBYTES);
|
|
V_UINT32("crypto_sign_PUBLICKEYBYTES", crypto_sign_PUBLICKEYBYTES);
|
|
V_UINT32("crypto_sign_SECRETKEYBYTES", crypto_sign_SECRETKEYBYTES);
|
|
V_UINT32("crypto_sign_BYTES", crypto_sign_BYTES);
|
|
|
|
// crypto_stream
|
|
|
|
V_FUNCTION("crypto_stream", sn_crypto_stream);
|
|
V_UINT32("crypto_stream_KEYBYTES", crypto_stream_KEYBYTES);
|
|
V_UINT32("crypto_stream_NONCEBYTES", crypto_stream_NONCEBYTES);
|
|
V_STRING("crypto_stream_PRIMITIVE", crypto_stream_PRIMITIVE);
|
|
|
|
V_FUNCTION_NOSCOPE("crypto_stream_xor", sn_crypto_stream_xor);
|
|
V_FUNCTION("crypto_stream_xor_init", sn_crypto_stream_xor_wrap_init);
|
|
V_FUNCTION("crypto_stream_xor_update", sn_crypto_stream_xor_wrap_update);
|
|
V_FUNCTION("crypto_stream_xor_final", sn_crypto_stream_xor_wrap_final);
|
|
V_UINT32("crypto_stream_xor_STATEBYTES", sizeof(sn_crypto_stream_xor_state));
|
|
|
|
V_FUNCTION("crypto_stream_chacha20", sn_crypto_stream_chacha20);
|
|
V_UINT32("crypto_stream_chacha20_KEYBYTES", crypto_stream_chacha20_KEYBYTES);
|
|
V_UINT32("crypto_stream_chacha20_NONCEBYTES", crypto_stream_chacha20_NONCEBYTES);
|
|
V_UINT64("crypto_stream_chacha20_MESSAGEBYTES_MAX", crypto_stream_chacha20_MESSAGEBYTES_MAX);
|
|
|
|
V_FUNCTION("crypto_stream_chacha20_xor", sn_crypto_stream_chacha20_xor);
|
|
V_FUNCTION("crypto_stream_chacha20_xor_ic", sn_crypto_stream_chacha20_xor_ic);
|
|
V_FUNCTION("crypto_stream_chacha20_xor_init", sn_crypto_stream_chacha20_xor_wrap_init);
|
|
V_FUNCTION("crypto_stream_chacha20_xor_update", sn_crypto_stream_chacha20_xor_wrap_update);
|
|
V_FUNCTION("crypto_stream_chacha20_xor_final", sn_crypto_stream_chacha20_xor_wrap_final);
|
|
V_UINT32("crypto_stream_chacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_xor_state));
|
|
|
|
V_FUNCTION("crypto_stream_chacha20_ietf", sn_crypto_stream_chacha20_ietf);
|
|
V_UINT32("crypto_stream_chacha20_ietf_KEYBYTES", crypto_stream_chacha20_ietf_KEYBYTES);
|
|
V_UINT32("crypto_stream_chacha20_ietf_NONCEBYTES", crypto_stream_chacha20_ietf_NONCEBYTES);
|
|
V_UINT64("crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX", crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX);
|
|
V_UINT32("crypto_stream_chacha20_ietf_xor_STATEBYTES", sizeof(sn_crypto_stream_chacha20_ietf_xor_state));
|
|
|
|
V_FUNCTION("crypto_stream_chacha20_ietf_xor", sn_crypto_stream_chacha20_ietf_xor);
|
|
V_FUNCTION("crypto_stream_chacha20_ietf_xor_ic", sn_crypto_stream_chacha20_ietf_xor_ic);
|
|
V_FUNCTION("crypto_stream_chacha20_ietf_xor_init", sn_crypto_stream_chacha20_ietf_xor_wrap_init);
|
|
V_FUNCTION("crypto_stream_chacha20_ietf_xor_update", sn_crypto_stream_chacha20_ietf_xor_wrap_update);
|
|
V_FUNCTION("crypto_stream_chacha20_ietf_xor_final", sn_crypto_stream_chacha20_ietf_xor_wrap_final);
|
|
|
|
V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
|
|
V_UINT32("crypto_stream_xchacha20_KEYBYTES", crypto_stream_xchacha20_KEYBYTES);
|
|
V_UINT32("crypto_stream_xchacha20_NONCEBYTES", crypto_stream_xchacha20_NONCEBYTES);
|
|
V_UINT64("crypto_stream_xchacha20_MESSAGEBYTES_MAX", crypto_stream_xchacha20_MESSAGEBYTES_MAX);
|
|
|
|
V_FUNCTION("crypto_stream_xchacha20_xor", sn_crypto_stream_xchacha20_xor);
|
|
V_FUNCTION("crypto_stream_xchacha20_xor_ic", sn_crypto_stream_xchacha20_xor_ic);
|
|
V_FUNCTION("crypto_stream_xchacha20_xor_init", sn_crypto_stream_xchacha20_xor_wrap_init);
|
|
V_FUNCTION("crypto_stream_xchacha20_xor_update", sn_crypto_stream_xchacha20_xor_wrap_update);
|
|
V_FUNCTION("crypto_stream_xchacha20_xor_final", sn_crypto_stream_xchacha20_xor_wrap_final);
|
|
V_FUNCTION("crypto_stream_xchacha20", sn_crypto_stream_xchacha20);
|
|
V_UINT32("crypto_stream_xchacha20_xor_STATEBYTES", sizeof(sn_crypto_stream_xchacha20_xor_state));
|
|
|
|
V_FUNCTION("crypto_stream_salsa20", sn_crypto_stream_salsa20);
|
|
V_UINT32("crypto_stream_salsa20_KEYBYTES", crypto_stream_salsa20_KEYBYTES);
|
|
V_UINT32("crypto_stream_salsa20_NONCEBYTES", crypto_stream_salsa20_NONCEBYTES);
|
|
V_UINT64("crypto_stream_salsa20_MESSAGEBYTES_MAX", crypto_stream_salsa20_MESSAGEBYTES_MAX);
|
|
|
|
V_FUNCTION("crypto_stream_salsa20_xor", sn_crypto_stream_salsa20_xor);
|
|
V_FUNCTION("crypto_stream_salsa20_xor_ic", sn_crypto_stream_salsa20_xor_ic);
|
|
V_FUNCTION("crypto_stream_salsa20_xor_init", sn_crypto_stream_salsa20_xor_wrap_init);
|
|
V_FUNCTION("crypto_stream_salsa20_xor_update", sn_crypto_stream_salsa20_xor_wrap_update);
|
|
V_FUNCTION("crypto_stream_salsa20_xor_final", sn_crypto_stream_salsa20_xor_wrap_final);
|
|
V_UINT32("crypto_stream_salsa20_xor_STATEBYTES", sizeof(sn_crypto_stream_salsa20_xor_state));
|
|
|
|
// extensions
|
|
|
|
// tweak
|
|
|
|
V_FUNCTION("extension_tweak_ed25519_base", sn_extension_tweak_ed25519_base);
|
|
V_FUNCTION("extension_tweak_ed25519_sign_detached", sn_extension_tweak_ed25519_sign_detached);
|
|
V_FUNCTION("extension_tweak_ed25519_sk_to_scalar", sn_extension_tweak_ed25519_sk_to_scalar);
|
|
V_FUNCTION("extension_tweak_ed25519_scalar", sn_extension_tweak_ed25519_scalar);
|
|
V_FUNCTION("extension_tweak_ed25519_pk", sn_extension_tweak_ed25519_pk);
|
|
V_FUNCTION("extension_tweak_ed25519_keypair", sn_extension_tweak_ed25519_keypair);
|
|
V_FUNCTION("extension_tweak_ed25519_scalar_add", sn_extension_tweak_ed25519_scalar_add);
|
|
V_FUNCTION("extension_tweak_ed25519_pk_add", sn_extension_tweak_ed25519_pk_add);
|
|
V_FUNCTION("extension_tweak_ed25519_keypair_add", sn_extension_tweak_ed25519_keypair_add);
|
|
V_UINT32("extension_tweak_ed25519_BYTES", sn__extension_tweak_ed25519_BYTES);
|
|
V_UINT32("extension_tweak_ed25519_SCALARBYTES", sn__extension_tweak_ed25519_SCALARBYTES);
|
|
|
|
// pbkdf2
|
|
|
|
V_FUNCTION("extension_pbkdf2_sha512", sn_extension_pbkdf2_sha512);
|
|
V_FUNCTION("extension_pbkdf2_sha512_async", sn_extension_pbkdf2_sha512_async);
|
|
V_UINT32("extension_pbkdf2_sha512_SALTBYTES", sn__extension_pbkdf2_sha512_SALTBYTES);
|
|
V_UINT32("extension_pbkdf2_sha512_HASHBYTES", sn__extension_pbkdf2_sha512_HASHBYTES);
|
|
V_UINT32("extension_pbkdf2_sha512_ITERATIONS_MIN", sn__extension_pbkdf2_sha512_ITERATIONS_MIN);
|
|
V_UINT64("extension_pbkdf2_sha512_BYTES_MAX", sn__extension_pbkdf2_sha512_BYTES_MAX);
|
|
|
|
#undef V_FUNCTION
|
|
#undef V_FUNCTION_NOSCOPE
|
|
#undef V_UINT32
|
|
#undef V_UINT64
|
|
#undef V_STRING
|
|
|
|
return exports;
|
|
}
|
|
|
|
BARE_MODULE(sodium_native, sodium_native_exports)
|