Current section
Files
Jump to
Current section
Files
c_src/sss_nif.c
/*
%%
%% erlang NIF binding for dsprenkel's sss library
%%
%% Copyright 2020 Alex Wilson <alex@uq.edu.au>, The University of Queensland
%%
%% Redistribution and use in source and binary forms, with or without
%% modification, are permitted provided that the following conditions
%% are met:
%% 1. Redistributions of source code must retain the above copyright
%% notice, this list of conditions and the following disclaimer.
%% 2. Redistributions in binary form must reproduce the above copyright
%% notice, this list of conditions and the following disclaimer in the
%% documentation and/or other materials provided with the distribution.
%%
%% THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
%% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
%% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
%% IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
%% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
%% NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
%% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
%% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
%% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
%% THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%%
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include "sss/sss.h"
#include "sss/hazmat.h"
#include "erl_nif.h"
static ERL_NIF_TERM
sss_nif_get_mlen(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
return (enif_make_uint(env, sss_MLEN));
}
static ERL_NIF_TERM
sss_nif_create_shares(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int n, k, i;
ErlNifBinary bin;
sss_Share *out;
ERL_NIF_TERM outbin, list, tmp;
if (!enif_get_uint(env, argv[1], &n))
return (enif_make_badarg(env));
if (!enif_get_uint(env, argv[2], &k))
return (enif_make_badarg(env));
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return (enif_make_badarg(env));
if (bin.size != sss_MLEN)
return (enif_make_badarg(env));
out = (sss_Share *)enif_make_new_binary(env,
n * sizeof (sss_Share), &outbin);
sss_create_shares(out, bin.data, n, k);
list = enif_make_list(env, 0);
for (i = 0; i < n; ++i) {
tmp = enif_make_sub_binary(env, outbin,
i * sizeof (sss_Share), sizeof (sss_Share));
list = enif_make_list_cell(env, tmp, list);
}
return (list);
}
static ERL_NIF_TERM
sss_nif_combine_shares(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int k;
ErlNifBinary bin;
uint8_t *out;
sss_Share *shares;
ERL_NIF_TERM ret;
int rc;
if (!enif_get_uint(env, argv[1], &k))
return (enif_make_badarg(env));
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return (enif_make_badarg(env));
if (bin.size != (sizeof (sss_Share) * k))
return (enif_make_atom(env, "error"));
shares = (sss_Share *)bin.data;
out = enif_make_new_binary(env, sss_MLEN, &ret);
rc = sss_combine_shares(out, shares, k);
if (rc == 0) {
ret = enif_make_tuple2(env, enif_make_atom(env, "ok"), ret);
} else {
ret = enif_make_atom(env, "error");
explicit_bzero(out, sss_MLEN);
}
return (ret);
}
static ERL_NIF_TERM
sss_nif_create_keyshares(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int n, k, i;
ErlNifBinary bin;
sss_Keyshare *out;
ERL_NIF_TERM outbin, list, tmp;
if (!enif_get_uint(env, argv[1], &n))
return (enif_make_badarg(env));
if (!enif_get_uint(env, argv[2], &k))
return (enif_make_badarg(env));
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return (enif_make_badarg(env));
if (bin.size != 32)
return (enif_make_badarg(env));
out = (sss_Keyshare *)enif_make_new_binary(env,
n * sizeof (sss_Keyshare), &outbin);
sss_create_keyshares(out, bin.data, n, k);
list = enif_make_list(env, 0);
for (i = 0; i < n; ++i) {
tmp = enif_make_sub_binary(env, outbin,
i * sizeof (sss_Keyshare), sizeof (sss_Keyshare));
list = enif_make_list_cell(env, tmp, list);
}
return (list);
}
static ERL_NIF_TERM
sss_nif_combine_keyshares(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
unsigned int k;
ErlNifBinary bin;
uint8_t *out;
sss_Keyshare *shares;
ERL_NIF_TERM ret;
if (!enif_get_uint(env, argv[1], &k))
return (enif_make_badarg(env));
if (!enif_inspect_iolist_as_binary(env, argv[0], &bin))
return (enif_make_badarg(env));
if (bin.size != (sizeof (sss_Keyshare) * k))
return (enif_make_badarg(env));
shares = (sss_Keyshare *)bin.data;
out = enif_make_new_binary(env, 32, &ret);
sss_combine_keyshares(out, shares, k);
return (ret);
}
static int
sss_nif_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM info)
{
return (0);
}
static void
sss_nif_unload(ErlNifEnv *env, void *priv_data)
{
}
static ErlNifFunc nif_funcs[] = {
{ "get_mlen", 0, sss_nif_get_mlen },
{ "create_shares", 3, sss_nif_create_shares },
{ "combine_shares", 2, sss_nif_combine_shares },
{ "create_keyshares", 3, sss_nif_create_keyshares },
{ "combine_keyshares", 2, sss_nif_combine_keyshares }
};
ERL_NIF_INIT(sss_nif, nif_funcs, sss_nif_load, NULL, NULL, sss_nif_unload);