Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/libexec/flua/libhash/lhash.c
103378 views
1
/*-
2
* Copyright (c) 2024 Netflix, Inc
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
7
#include <lua.h>
8
#include "lauxlib.h"
9
#include "lhash.h"
10
11
#include <sha256.h>
12
#include <string.h>
13
14
#include "bootstrap.h"
15
16
#define SHA256_META "SHA256 meta table"
17
#define SHA256_DIGEST_LEN 32
18
19
/*
20
* Note C++ comments indicate the before -- after state of the stack, in with a
21
* similar convention to forth's ( ) comments. Lua indexes are from 1 and can be
22
* read left to right (leftmost is 1). Negative are relative to the end (-1 is
23
* rightmost). A '.' indicates a return value left on the stack (all values to
24
* its right). Trivial functions don't do this.
25
*/
26
27
/*
28
* Updates the digest with the new data passed in. Takes 1 argument, which
29
* is converted to a string.
30
*/
31
static int
32
lua_sha256_update(lua_State *L)
33
{
34
size_t len;
35
const unsigned char *data;
36
SHA256_CTX *ctx;
37
38
ctx = luaL_checkudata(L, 1, SHA256_META);
39
data = luaL_checklstring(L, 2, &len);
40
SHA256_Update(ctx, data, len);
41
42
lua_settop(L, 1);
43
44
return (1);
45
}
46
47
/*
48
* Finalizes the digest value and returns it as a 32-byte binary string. The ctx
49
* is zeroed.
50
*/
51
static int
52
lua_sha256_digest(lua_State *L)
53
{
54
SHA256_CTX *ctx;
55
unsigned char digest[SHA256_DIGEST_LEN];
56
57
ctx = luaL_checkudata(L, 1, SHA256_META);
58
SHA256_Final(digest, ctx);
59
lua_pushlstring(L, digest, sizeof(digest));
60
61
return (1);
62
}
63
64
/*
65
* Finalizes the digest value and returns it as a 64-byte ascii string of hex
66
* numbers. The ctx is zeroed.
67
*/
68
static int
69
lua_sha256_hexdigest(lua_State *L)
70
{
71
SHA256_CTX *ctx;
72
char buf[SHA256_DIGEST_LEN * 2 + 1];
73
unsigned char digest[SHA256_DIGEST_LEN];
74
static const char hex[]="0123456789abcdef";
75
int i;
76
77
ctx = luaL_checkudata(L, 1, SHA256_META);
78
SHA256_Final(digest, ctx);
79
for (i = 0; i < SHA256_DIGEST_LEN; i++) {
80
buf[i+i] = hex[digest[i] >> 4];
81
buf[i+i+1] = hex[digest[i] & 0x0f];
82
}
83
buf[i+i] = '\0';
84
85
lua_pushstring(L, buf);
86
87
return (1);
88
}
89
90
/*
91
* Zeros out the ctx before garbage collection. Normally this is done in
92
* obj:digest or obj:hexdigest, but if not, it will be wiped here. Lua
93
* manages freeing the ctx memory.
94
*/
95
static int
96
lua_sha256_done(lua_State *L)
97
{
98
SHA256_CTX *ctx;
99
100
ctx = luaL_checkudata(L, 1, SHA256_META);
101
memset(ctx, 0, sizeof(*ctx));
102
103
return (0);
104
}
105
106
/*
107
* Create object obj which accumulates the state of the sha256 digest
108
* for its contents and any subsequent obj:update call. It takes zero
109
* or 1 arguments.
110
*/
111
static int
112
lua_sha256(lua_State *L)
113
{
114
SHA256_CTX *ctx;
115
int top;
116
117
/* We take 0 or 1 args */
118
top = lua_gettop(L); // data -- data
119
if (top > 1) {
120
lua_pushnil(L);
121
return (1);
122
}
123
124
ctx = lua_newuserdata(L, sizeof(*ctx)); // data -- data ctx
125
SHA256_Init(ctx);
126
if (top == 1) {
127
size_t len;
128
const unsigned char *data;
129
130
data = luaL_checklstring(L, 1, &len);
131
SHA256_Update(ctx, data, len);
132
}
133
luaL_setmetatable(L, SHA256_META); // data ctx -- data ctx
134
135
return (1); // data . ctx
136
}
137
138
/*
139
* Setup the metatable to manage our userdata that we create in lua_sha256. We
140
* request a finalization call with __gc so we can zero out the ctx buffer so
141
* that we don't leak secrets if obj:digest or obj:hexdigest aren't called.
142
*/
143
static void
144
register_metatable_sha256(lua_State *L)
145
{
146
luaL_newmetatable(L, SHA256_META); // -- meta
147
148
lua_newtable(L); // meta -- meta tbl
149
lua_pushcfunction(L, lua_sha256_update); // meta tbl -- meta tbl fn
150
lua_setfield(L, -2, "update"); // meta tbl fn -- meta tbl
151
lua_pushcfunction(L, lua_sha256_digest); // meta tbl -- meta tbl fn
152
lua_setfield(L, -2, "digest"); // meta tbl fn -- meta tbl
153
lua_pushcfunction(L, lua_sha256_hexdigest); // meta tbl -- meta tbl fn
154
lua_setfield(L, -2, "hexdigest"); // meta tbl fn -- meta tbl
155
156
/* Associate tbl with metatable */
157
lua_setfield(L, -2, "__index"); // meta tbl -- meta
158
lua_pushcfunction(L, lua_sha256_done); // meta -- meta fn
159
lua_setfield(L, -2, "__gc"); // meta fn -- meta
160
161
lua_pop(L, 1); // meta --
162
}
163
164
#define REG_SIMPLE(n) { #n, lua_ ## n }
165
static const struct luaL_Reg hashlib[] = {
166
REG_SIMPLE(sha256),
167
{ NULL, NULL },
168
};
169
#undef REG_SIMPLE
170
171
int
172
luaopen_hash(lua_State *L)
173
{
174
register_metatable_sha256(L);
175
176
luaL_newlib(L, hashlib);
177
178
return 1;
179
}
180
181
#ifndef _STANDALONE
182
FLUA_MODULE(hash);
183
#endif
184
185