#include <lua.h>
#include "lauxlib.h"
#include "lhash.h"
#include <sha256.h>
#include <string.h>
#include "bootstrap.h"
#define SHA256_META "SHA256 meta table"
#define SHA256_DIGEST_LEN 32
static int
lua_sha256_update(lua_State *L)
{
size_t len;
const unsigned char *data;
SHA256_CTX *ctx;
ctx = luaL_checkudata(L, 1, SHA256_META);
data = luaL_checklstring(L, 2, &len);
SHA256_Update(ctx, data, len);
lua_settop(L, 1);
return (1);
}
static int
lua_sha256_digest(lua_State *L)
{
SHA256_CTX *ctx;
unsigned char digest[SHA256_DIGEST_LEN];
ctx = luaL_checkudata(L, 1, SHA256_META);
SHA256_Final(digest, ctx);
lua_pushlstring(L, digest, sizeof(digest));
return (1);
}
static int
lua_sha256_hexdigest(lua_State *L)
{
SHA256_CTX *ctx;
char buf[SHA256_DIGEST_LEN * 2 + 1];
unsigned char digest[SHA256_DIGEST_LEN];
static const char hex[]="0123456789abcdef";
int i;
ctx = luaL_checkudata(L, 1, SHA256_META);
SHA256_Final(digest, ctx);
for (i = 0; i < SHA256_DIGEST_LEN; i++) {
buf[i+i] = hex[digest[i] >> 4];
buf[i+i+1] = hex[digest[i] & 0x0f];
}
buf[i+i] = '\0';
lua_pushstring(L, buf);
return (1);
}
static int
lua_sha256_done(lua_State *L)
{
SHA256_CTX *ctx;
ctx = luaL_checkudata(L, 1, SHA256_META);
memset(ctx, 0, sizeof(*ctx));
return (0);
}
static int
lua_sha256(lua_State *L)
{
SHA256_CTX *ctx;
int top;
top = lua_gettop(L);
if (top > 1) {
lua_pushnil(L);
return (1);
}
ctx = lua_newuserdata(L, sizeof(*ctx));
SHA256_Init(ctx);
if (top == 1) {
size_t len;
const unsigned char *data;
data = luaL_checklstring(L, 1, &len);
SHA256_Update(ctx, data, len);
}
luaL_setmetatable(L, SHA256_META);
return (1);
}
static void
register_metatable_sha256(lua_State *L)
{
luaL_newmetatable(L, SHA256_META);
lua_newtable(L);
lua_pushcfunction(L, lua_sha256_update);
lua_setfield(L, -2, "update");
lua_pushcfunction(L, lua_sha256_digest);
lua_setfield(L, -2, "digest");
lua_pushcfunction(L, lua_sha256_hexdigest);
lua_setfield(L, -2, "hexdigest");
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lua_sha256_done);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
}
#define REG_SIMPLE(n) { #n, lua_ ## n }
static const struct luaL_Reg hashlib[] = {
REG_SIMPLE(sha256),
{ NULL, NULL },
};
#undef REG_SIMPLE
int
luaopen_hash(lua_State *L)
{
register_metatable_sha256(L);
luaL_newlib(L, hashlib);
return 1;
}
#ifndef _STANDALONE
FLUA_MODULE(hash);
#endif