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