Split extension functions away

This commit is contained in:
Jesper Louis Andersen 2020-02-05 12:08:28 +01:00
parent d06fff489d
commit 78621356ec
3 changed files with 102 additions and 84 deletions

86
c_src/enacl_ext.c Normal file
View File

@ -0,0 +1,86 @@
#include <sodium.h>
#include <erl_nif.h>
#include "enacl.h"
#include "enacl_ext.h"
static void uint64_pack(unsigned char *y, ErlNifUInt64 x) {
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
}
static ErlNifUInt64 uint64_unpack(const unsigned char *x) {
ErlNifUInt64 result;
result = x[7];
result <<= 8;
result |= x[6];
result <<= 8;
result |= x[5];
result <<= 8;
result |= x[4];
result <<= 8;
result |= x[3];
result <<= 8;
result |= x[2];
result <<= 8;
result |= x[1];
result <<= 8;
result |= x[0];
return result;
}
static int crypto_block(unsigned char *out, const unsigned char *in,
const unsigned char *k) {
ErlNifUInt64 v0 = uint64_unpack(in + 0);
ErlNifUInt64 v1 = uint64_unpack(in + 8);
ErlNifUInt64 k0 = uint64_unpack(k + 0);
ErlNifUInt64 k1 = uint64_unpack(k + 8);
ErlNifUInt64 k2 = uint64_unpack(k + 16);
ErlNifUInt64 k3 = uint64_unpack(k + 24);
ErlNifUInt64 sum = 0;
ErlNifUInt64 delta = 0x9e3779b97f4a7c15;
int i;
for (i = 0; i < 32; ++i) {
sum += delta;
v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1);
v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3);
}
uint64_pack(out + 0, v0);
uint64_pack(out + 8, v1);
return 0;
}
ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary in, out, key;
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) ||
(!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) ||
(key.size != 32)) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(in.size, &out)) {
return enacl_error_tuple(env, "alloc_failed");
}
crypto_block(out.data, in.data, key.data);
return enif_make_binary(env, &out);
}

9
c_src/enacl_ext.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef ENACL_EXT_H
#define ENACL_EXT_H
#include <erl_nif.h>
ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]);
#endif

View File

@ -5,6 +5,7 @@
#include "aead.h"
#include "enacl.h"
#include "enacl_ext.h"
#include "generichash.h"
#include "hash.h"
#include "kx.h"
@ -121,11 +122,12 @@ enacl_crypto_curve25519_scalarmult(ErlNifEnv *env, int argc,
do {
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) {
result = enacl_error_tuple(env, "alloc_failed");
result = enacl_internal_error(env);
continue;
}
if (crypto_scalarmult_curve25519(output.data, secret.data, bp) < 0) {
if (crypto_scalarmult_curve25519(output.data, secret.data, bp) != 0) {
enif_release_binary(&output);
result = enacl_error_tuple(env, "scalarmult_curve25519_failed");
continue;
}
@ -151,11 +153,12 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc,
do {
if (!enif_alloc_binary(crypto_scalarmult_curve25519_BYTES, &output)) {
result = enacl_error_tuple(env, "alloc_failed");
result = enacl_internal_error(env);
continue;
}
if (crypto_scalarmult_curve25519_base(output.data, secret.data) < 0) {
if (crypto_scalarmult_curve25519_base(output.data, secret.data) != 0) {
enif_release_binary(&output);
result = enacl_error_tuple(env, "scalarmult_curve25519_base_failed");
continue;
}
@ -166,86 +169,6 @@ enacl_crypto_curve25519_scalarmult_base(ErlNifEnv *env, int argc,
return result;
}
/* Various other helper functions */
static void uint64_pack(unsigned char *y, ErlNifUInt64 x) {
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
x >>= 8;
*y++ = x;
}
static ErlNifUInt64 uint64_unpack(const unsigned char *x) {
ErlNifUInt64 result;
result = x[7];
result <<= 8;
result |= x[6];
result <<= 8;
result |= x[5];
result <<= 8;
result |= x[4];
result <<= 8;
result |= x[3];
result <<= 8;
result |= x[2];
result <<= 8;
result |= x[1];
result <<= 8;
result |= x[0];
return result;
}
static int crypto_block(unsigned char *out, const unsigned char *in,
const unsigned char *k) {
ErlNifUInt64 v0 = uint64_unpack(in + 0);
ErlNifUInt64 v1 = uint64_unpack(in + 8);
ErlNifUInt64 k0 = uint64_unpack(k + 0);
ErlNifUInt64 k1 = uint64_unpack(k + 8);
ErlNifUInt64 k2 = uint64_unpack(k + 16);
ErlNifUInt64 k3 = uint64_unpack(k + 24);
ErlNifUInt64 sum = 0;
ErlNifUInt64 delta = 0x9e3779b97f4a7c15;
int i;
for (i = 0; i < 32; ++i) {
sum += delta;
v0 += ((v1 << 7) + k0) ^ (v1 + sum) ^ ((v1 >> 12) + k1);
v1 += ((v0 << 16) + k2) ^ (v0 + sum) ^ ((v0 >> 8) + k3);
}
uint64_pack(out + 0, v0);
uint64_pack(out + 8, v1);
return 0;
}
static ERL_NIF_TERM enif_scramble_block_16(ErlNifEnv *env, int argc,
ERL_NIF_TERM const argv[]) {
ErlNifBinary in, out, key;
if ((argc != 2) || (!enif_inspect_binary(env, argv[0], &in)) ||
(!enif_inspect_binary(env, argv[1], &key)) || (in.size != 16) ||
(key.size != 32)) {
return enif_make_badarg(env);
}
if (!enif_alloc_binary(in.size, &out)) {
return enacl_error_tuple(env, "alloc_failed");
}
crypto_block(out.data, in.data, key.data);
return enif_make_binary(env, &out);
}
/* Tie the knot to the Erlang world */
static ErlNifFunc nif_funcs[] = {
{"crypto_box_NONCEBYTES", 0, enacl_crypto_box_NONCEBYTES},