The branch stable/14 has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ae8398452bd3196c0ff1a11039167bd002369eb8

commit ae8398452bd3196c0ff1a11039167bd002369eb8
Author:     Warner Losh <[email protected]>
AuthorDate: 2024-02-16 03:54:36 +0000
Commit:     Warner Losh <[email protected]>
CommitDate: 2024-04-16 19:54:20 +0000

    flua: Add hash module
    
    Add lua bindings to hashing functions. sha256 is available. sha256.new
    craetes a new object. sha256.update updates the digest. sha256.digest
    returns the digest as a binary string and resets the
    context. sha256.hexdigest returns the digest as a string of hex digits
    and then resets the cotnext.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D43872
    
    (cherry picked from commit f7781d030ccd18b1d4c864ecfade122ea19dafb1)
---
 lib/flua/Makefile          |   4 +-
 lib/flua/libhash/Makefile  |  14 ++++
 lib/flua/libhash/hash.3lua |  54 ++++++++++++++
 lib/flua/libhash/lhash.c   | 177 +++++++++++++++++++++++++++++++++++++++++++++
 lib/flua/libhash/lhash.h   |  11 +++
 5 files changed, 258 insertions(+), 2 deletions(-)

diff --git a/lib/flua/Makefile b/lib/flua/Makefile
index eb148c2125fd..769736039f7e 100644
--- a/lib/flua/Makefile
+++ b/lib/flua/Makefile
@@ -1,4 +1,4 @@
-
-SUBDIR=        libjail
+SUBDIR+=       libhash
+SUBDIR+=       libjail
 
 .include <bsd.subdir.mk>
diff --git a/lib/flua/libhash/Makefile b/lib/flua/libhash/Makefile
new file mode 100644
index 000000000000..f166ff90a392
--- /dev/null
+++ b/lib/flua/libhash/Makefile
@@ -0,0 +1,14 @@
+SHLIB_NAME=    hash.so
+SHLIBDIR=      ${LIBDIR}/flua
+
+SRCS+=         lhash.c
+
+CFLAGS+= \
+       -I${SRCTOP}/contrib/lua/src \
+       -I${SRCTOP}/lib/liblua \
+
+LIBADD+=       md
+
+MAN=   hash.3lua
+
+.include <bsd.lib.mk>
diff --git a/lib/flua/libhash/hash.3lua b/lib/flua/libhash/hash.3lua
new file mode 100644
index 000000000000..1662e87f7c68
--- /dev/null
+++ b/lib/flua/libhash/hash.3lua
@@ -0,0 +1,54 @@
+.\"
+.\" Copyright (c) 2024 Netflix, Inc.
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.Dd February 6, 2024
+.Dt HASH 3lua
+.Os
+.Sh NAME
+.Nm new ,
+.Nm update ,
+.Nm digest ,
+.Nm hexdigest
+.Nd Lua Cryptographic hash module.
+.Sh DESCRIPTION
+The built-in cryptographic hashing Lua bindings for the are available via the
+.Ic hash
+table.
+.Ss Supported Hashing Schemes
+The following hashing schemes are supported by the hash module.
+.Bl -bullet -compact
+.It
+sha256
+.El
+.Ss APIs Supported
+.Bl -tag -width asdf -compact
+.It Fn new data
+Compute a digest based on the
+.Va data .
+.It Fn update Va data
+Using the current digest, process
+.Va data
+to compute a new digest as if all prior data had been concatenated together.
+.It Fn digest
+Return the hashed digest as a binary array.
+This resets the context.
+.It Fn hexdigest
+Take
+.Fn digest
+and convert it to an upper case hex string.
+This resets the context.
+.It Va digest_size
+Return the size of the digest, in bytes.
+.It Va block_size
+Return the block size used in bytes.
+.El
+.Sh EXAMPLES
+.Sh SEE ALSO
+.Xr sha256 3
+.Sh AUTHORS
+The
+.Nm
+man page was written by
+.An Warner Losh Aq Mt [email protected] .
diff --git a/lib/flua/libhash/lhash.c b/lib/flua/libhash/lhash.c
new file mode 100644
index 000000000000..4587961fe8a0
--- /dev/null
+++ b/lib/flua/libhash/lhash.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2024 Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <lua.h>
+#include "lauxlib.h"
+#include "lhash.h"
+
+#include <sha256.h>
+#include <string.h>
+
+#define SHA256_META "SHA256 meta table"
+#define SHA256_DIGEST_LEN 32
+
+/*
+ * Note C++ comments indicate the before -- after state of the stack, in with a
+ * similar convention to forth's ( ) comments. Lua indexes are from 1 and can 
be
+ * read left to right (leftmost is 1). Negative are relative to the end (-1 is
+ * rightmost). A '.' indicates a return value left on the stack (all values to
+ * its right). Trivial functions don't do this.
+ */
+
+/*
+ * Updates the digest with the new data passed in. Takes 1 argument, which
+ * is converted to a string.
+ */
+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);
+}
+
+/*
+ * Finalizes the digest value and returns it as a 32-byte binary string. The 
ctx
+ * is zeroed.
+ */
+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);
+}
+
+/*
+ * Finalizes the digest value and returns it as a 64-byte ascii string of hex
+ * numbers. The ctx is zeroed.
+ */
+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);
+}
+
+/*
+ * Zeros out the ctx before garbage collection. Normally this is done in
+ * obj:digest or obj:hexdigest, but if not, it will be wiped here. Lua
+ * manages freeing the ctx memory.
+ */
+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);
+}
+
+/*
+ * Create object obj which accumulates the state of the sha256 digest
+ * for its contents and any subsequent obj:update call. It takes zero
+ * or 1 arguments.
+ */
+static int
+lua_sha256(lua_State *L)
+{
+       SHA256_CTX *ctx;
+       int top;
+
+       /* We take 0 or 1 args */
+       top = lua_gettop(L);                            // data -- data
+       if (top > 1) {
+               lua_pushnil(L);
+               return (1);
+       }
+
+       ctx = lua_newuserdata(L, sizeof(*ctx));         // data -- data 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);              // data ctx -- data ctx
+
+       return (1);                                     // data . ctx
+}
+
+/*
+ * Setup the metatable to manage our userdata that we create in lua_sha256. We
+ * request a finalization call with __gc so we can zero out the ctx buffer so
+ * that we don't leak secrets if obj:digest or obj:hexdigest aren't called.
+ */
+static void
+register_metatable_sha256(lua_State *L)
+{
+       luaL_newmetatable(L, SHA256_META);              // -- meta
+
+       lua_newtable(L);                                // meta -- meta tbl
+       lua_pushcfunction(L, lua_sha256_update);        // meta tbl -- meta tbl 
fn
+       lua_setfield(L, -2, "update");                  // meta tbl fn -- meta 
tbl
+       lua_pushcfunction(L, lua_sha256_digest);        // meta tbl -- meta tbl 
fn
+       lua_setfield(L, -2, "digest");                  // meta tbl fn -- meta 
tbl
+       lua_pushcfunction(L, lua_sha256_hexdigest);     // meta tbl -- meta tbl 
fn
+       lua_setfield(L, -2, "hexdigest");               // meta tbl fn -- meta 
tbl
+
+       /* Associate tbl with metatable */
+       lua_setfield(L, -2, "__index");                 // meta tbl -- meta
+       lua_pushcfunction(L, lua_sha256_done);          // meta -- meta fn
+       lua_setfield(L, -2, "__gc");                    // meta fn -- meta
+
+       lua_pop(L, 1);                                  // meta --
+}
+
+#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;
+}
diff --git a/lib/flua/libhash/lhash.h b/lib/flua/libhash/lhash.h
new file mode 100644
index 000000000000..c1e9788a55a3
--- /dev/null
+++ b/lib/flua/libhash/lhash.h
@@ -0,0 +1,11 @@
+/*-
+ * Copyright (c) 2024 Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <lua.h>
+
+int luaopen_hash(lua_State *L);

Reply via email to