-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcommon.c
216 lines (196 loc) · 4.63 KB
/
common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
static void update(struct HASH_NAME *ctx, const uint8_t *in, size_t len)
{
while (len) {
int room = HASH_UPDATE - ctx->used;
if (room > 0) {
if (room > len)
room = len;
memcpy(ctx->buf + ctx->used, in, room);
in += room;
ctx->used += room;
ctx->total += room;
len -= room;
}
if (ctx->used == HASH_UPDATE) {
transform(ctx->state, ctx->buf);
ctx->used = 0;
}
}
}
static void reset(struct HASH_NAME *ctx)
{
memset(ctx, 0, sizeof(*ctx));
#if (HASH_FLAGS) & HASH_INIT
{
int i;
for (i = 0; i < HASH_WORDS; i++)
ctx->state[i] = init[i];
}
#endif
}
#if (HASH_FLAGS) & HASH_MD
static void final(struct HASH_NAME *ctx, uint8_t *out)
{
uint8_t buf[HASH_UPDATE];
uint32_t i, used = ctx->used;
HASH_WORD state[HASH_WORDS];
memcpy(buf, ctx->buf, HASH_UPDATE);
memcpy(state, ctx->state, sizeof(state));
buf[used++] = 0x80;
if (used <= (HASH_UPDATE-8)) {
memset(buf + used, 0, (HASH_UPDATE-8)-used);
} else {
memset(buf + used, 0, HASH_UPDATE-used);
transform(state, buf);
memset(buf, 0, HASH_UPDATE-8);
}
*((uint64_t*)(buf+HASH_UPDATE-8)) = HOST2HASH64(ctx->total<<3);
transform(state, buf);
for (i = 0; i < HASH_WORDS; i++)
((HASH_WORD*)(out))[i] = HOST2HASH(state[i]);
}
#endif
static struct HASH_NAME *toctx(lua_State *L, int idx)
{
void *d = lua_touserdata(L, idx);
if (d) {
if (lua_getmetatable(L, idx)) {
if (!lua_rawequal(L, -1, lua_upvalueindex(1)))
d = NULL;
lua_pop(L, 1);
} else d = NULL;
}
if (!d)
luaL_argerror(L, idx, "expected " hash_name " object");
return d;
}
static void do_updates(lua_State *L, struct HASH_NAME *ctx, int from, int to)
{
int i;
for (i = from; i <= to; i++) {
size_t l;
const char *s = luaL_checklstring(L, i, &l);
update(ctx, (const uint8_t*)s, l);
}
}
static void do_hmac(struct HASH_NAME *ctx, const uint8_t *key, size_t keysz,
const uint8_t *data, size_t datasz)
{
int i;
uint8_t ikey[HASH_UPDATE], okey[HASH_UPDATE];
uint8_t buf[HASH_UPDATE] = {0};
reset(ctx);
if (keysz > HASH_UPDATE) {
update(ctx, (const uint8_t*)key, keysz);
final(ctx, buf);
reset(ctx);
} else {
memcpy(buf, key, keysz);
}
for (i = 0; i < HASH_UPDATE; i++) {
okey[i] = buf[i] ^ 0x5c;
ikey[i] = buf[i] ^ 0x36;
}
update(ctx, ikey, HASH_UPDATE);
update(ctx, (const uint8_t*)data, datasz);
final(ctx, buf);
reset(ctx);
update(ctx, okey, HASH_UPDATE);
update(ctx, buf, HASH_BYTES);
}
#if (HASH_FLAGS) & HASH_HMAC
static int m_hmac(lua_State *L)
{
struct HASH_NAME *ctx = toctx(L, 1);
size_t keysz, datasz;
const char *key = luaL_checklstring(L, 2, &keysz);
const char *data = luaL_checklstring(L, 3, &datasz);
do_hmac(ctx, (const uint8_t*)key, keysz, (const uint8_t*)data, datasz);
lua_settop(L, 1);
return 1;
}
#endif
static int m_create(lua_State *L)
{
struct HASH_NAME *ctx = lua_newuserdata(L, sizeof(struct HASH_NAME));
reset(ctx);
lua_pushvalue(L, lua_upvalueindex(1));
lua_setmetatable(L, -2);
do_updates(L, ctx, 1, lua_gettop(L)-1);
return 1;
}
static int m_clone(lua_State *L)
{
struct HASH_NAME *nctx, *ctx = toctx(L, 1);
nctx = lua_newuserdata(L, sizeof(struct HASH_NAME));
*nctx = *ctx;
lua_pushvalue(L, lua_upvalueindex(1));
lua_setmetatable(L, -2);
do_updates(L, nctx, 2, lua_gettop(L)-1);
return 1;
}
static int m_reset(lua_State *L)
{
struct HASH_NAME *ctx = toctx(L, 1);
reset(ctx);
do_updates(L, ctx, 2, lua_gettop(L));
lua_settop(L, 1);
return 1;
}
static int m_update(lua_State *L)
{
struct HASH_NAME *ctx = toctx(L, 1);
do_updates(L, ctx, 2, lua_gettop(L));
lua_settop(L, 1);
return 1;
}
static int m_digest(lua_State *L)
{
struct HASH_NAME *ctx = toctx(L, 1);
uint8_t buf[HASH_BYTES];
do_updates(L, ctx, 2, lua_gettop(L));
final(ctx, buf);
lua_pushlstring(L, (const char*)buf, sizeof buf);
return 1;
}
static int m_hexdigest(lua_State *L)
{
static const char tab[16] = "0123456789abcdef";
struct HASH_NAME *ctx = toctx(L, 1);
uint8_t buf[HASH_BYTES];
char buf2[HASH_BYTES*2+1];
int i;
do_updates(L, ctx, 2, lua_gettop(L));
final(ctx, buf);
for (i = 0; i < HASH_BYTES; i++) {
buf2[i*2] = tab[buf[i]/16];
buf2[i*2+1] = tab[buf[i]%16];
}
buf2[HASH_BYTES*2] = 0;
lua_pushlstring(L, buf2, HASH_BYTES*2);
return 1;
}
static const luaL_Reg methods[] = {
{"clone", m_clone},
{"reset", m_reset},
{"update", m_update},
{"digest", m_digest},
{"hexdigest", m_hexdigest},
{"hex", m_hexdigest},
#if (HASH_FLAGS) & HASH_HMAC
{"hmac", m_hmac},
#endif
{NULL, NULL}
};
static int lua_binding(lua_State *L)
{
lua_newtable(L);
lua_pushvalue(L, -1);
luaL_setfuncs(L, methods, 1);
lua_pushvalue(L, -1);
lua_setmetatable(L, -2);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushcclosure(L, m_create, 1);
return 1;
}