nodemcu-firmware/components/modules/sodium.c

153 lines
4.0 KiB
C

#include "module.h"
#include "lauxlib.h"
#include "lmem.h"
#include "sodium.h"
static void check_init(lua_State *L)
{
if (sodium_init() == -1) {
luaL_error(L, "sodium_init returned an error");
}
}
// https://download.libsodium.org/doc/generating_random_data
static int l_randombytes_random(lua_State *L)
{
check_init(L);
uint32_t ret = randombytes_random();
lua_pushnumber(L, (lua_Number)ret);
return 1;
}
static int l_randombytes_uniform(lua_State *L)
{
check_init(L);
uint32_t upper_bound = (uint32_t)luaL_checkinteger(L, 1);
uint32_t ret = randombytes_uniform(upper_bound);
lua_pushnumber(L, (lua_Number)ret);
return 1;
}
static int l_randombytes_buf(lua_State *L)
{
check_init(L);
size_t count = (size_t)luaL_checkinteger(L, 1);
if (count <= LUAL_BUFFERSIZE) {
luaL_Buffer b;
luaL_buffinit(L, &b);
randombytes_buf(luaL_prepbuffer(&b), count);
luaL_addsize(&b, count);
luaL_pushresult(&b);
} else {
char *buf = (char *)luaM_malloc(L, count);
randombytes_buf(buf, count);
lua_pushlstring(L, buf, count);
luaM_freemem(L, buf, count);
}
return 1;
}
// See https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes
static int l_crypto_box_keypair(lua_State *L)
{
check_init(L);
unsigned char pk[crypto_box_PUBLICKEYBYTES];
unsigned char sk[crypto_box_SECRETKEYBYTES];
int err = crypto_box_keypair(pk, sk);
if (err) {
return luaL_error(L, "crypto_box_keypair returned %d", err);
}
lua_pushlstring(L, (char *)pk, sizeof(pk));
lua_pushlstring(L, (char *)sk, sizeof(sk));
return 2;
}
static const uint8_t * get_pk(lua_State *L, int idx)
{
check_init(L);
size_t pk_len;
const char *pk = luaL_checklstring(L, 2, &pk_len);
if (pk_len != crypto_box_PUBLICKEYBYTES) {
luaL_error(L, "Bad public key size!");
}
return (const uint8_t *)pk;
}
static const uint8_t * get_sk(lua_State *L, int idx)
{
check_init(L);
size_t sk_len;
const char *sk = luaL_checklstring(L, idx, &sk_len);
if (sk_len != crypto_box_SECRETKEYBYTES) {
luaL_error(L, "Bad secret key size!");
}
return (const uint8_t *)sk;
}
static int l_crypto_box_seal(lua_State *L)
{
check_init(L);
size_t msg_len;
const uint8_t *msg = (const uint8_t *)luaL_checklstring(L, 1, &msg_len);
const uint8_t *pk = get_pk(L, 2);
const size_t ciphertext_len = crypto_box_SEALBYTES + msg_len;
uint8_t *ciphertext = (uint8_t *)luaM_malloc(L, ciphertext_len);
int err = crypto_box_seal(ciphertext, msg, msg_len, pk);
if (err) {
luaM_freemem(L, ciphertext, ciphertext_len);
return luaL_error(L, "crypto_box_seal returned %d", err);
}
lua_pushlstring(L, (char *)ciphertext, ciphertext_len);
luaM_freemem(L, ciphertext, ciphertext_len);
return 1;
}
static int l_crypto_box_seal_open(lua_State *L)
{
check_init(L);
size_t ciphertext_len;
const uint8_t *ciphertext = (const uint8_t *)luaL_checklstring(L, 1, &ciphertext_len);
const uint8_t *pk = get_pk(L, 2);
const uint8_t *sk = get_sk(L, 3);
const size_t decrypted_len = ciphertext_len - crypto_box_SEALBYTES;
uint8_t *decrypted = (uint8_t *)luaM_malloc(L, decrypted_len);
int err = crypto_box_seal_open(decrypted, ciphertext, ciphertext_len, pk, sk);
if (err) {
lua_pushnil(L);
} else {
lua_pushlstring(L, (char *)decrypted, decrypted_len);
}
luaM_freemem(L, decrypted, decrypted_len);
return 1;
}
static const LUA_REG_TYPE random_map[] = {
{ LSTRKEY("random"), LFUNCVAL(l_randombytes_random) },
{ LSTRKEY("uniform"), LFUNCVAL(l_randombytes_uniform) },
{ LSTRKEY("buf"), LFUNCVAL(l_randombytes_buf) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE crypto_box_map[] = {
{ LSTRKEY("keypair"), LFUNCVAL(l_crypto_box_keypair) },
{ LSTRKEY("seal"), LFUNCVAL(l_crypto_box_seal) },
{ LSTRKEY("seal_open"), LFUNCVAL(l_crypto_box_seal_open) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE sodium_map[] = {
{ LSTRKEY("random"), LROVAL(random_map) },
{ LSTRKEY("crypto_box"), LROVAL(crypto_box_map) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SODIUM, "sodium", sodium_map, NULL);