forked from starius/luacryptor
/
lua_bindings.c
148 lines (136 loc) · 3.88 KB
/
lua_bindings.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
#include <stdio.h>
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
static void get_random_bytes(char* buffer, int size) {
FILE* urandom = fopen("/dev/urandom", "r");
fread(buffer, size, 1, urandom);
fclose(urandom);
}
static void xor_block(BYTE* dst, const BYTE* src, int size) {
int i;
for (i = 0; i < size; i++) {
dst[i] ^= src[i];
}
}
#define BLOCK_BYTES 16
static void xor_ctr(unsigned char* block, unsigned int ctr) {
unsigned char* current_byte = block + BLOCK_BYTES - 1;
while (ctr) {
*current_byte ^= ctr & 0xFF;
ctr >>= 8;
current_byte -= 1;
}
}
static void calc_sha256(BYTE* buffer32,
const uint8* text, size_t size) {
sha256_context ctx;
sha256_starts(&ctx);
sha256_update(&ctx, (uint8*)text, size);
sha256_finish(&ctx, buffer32);
}
// If encr, encrypts, otherwise decrypts
// Lua arguments:
// string text (may be cleartext or encrypted text)
// string password
// sha256(password) is used as key for twofish
// returns cleartext or encrypted text
static int twofish_twoways(lua_State *L, int encr) {
if (lua_gettop(L) != 2) {
return 0;
}
if (lua_type(L, 1) != LUA_TSTRING) {
return 0;
}
if (lua_type(L, 2) != LUA_TSTRING) {
return 0;
}
size_t text_s;
const char* text = lua_tolstring(L, 1, &text_s);
size_t password_s;
const char* password = lua_tolstring(L, 2, &password_s);
// sha256
unsigned char sha256sum[32];
calc_sha256(sha256sum, password, password_s);
// twofish - prepare key
u32 *S;
u32 K[40];
int k;
keySched(sha256sum, 256, &S, K, &k);
u32 QF[4][256];
fullKey(S, k, QF);
free(S);
// allocate output string
// nonce is stored in the beginning
int result_bytes;
if (encr) {
result_bytes = text_s + BLOCK_BYTES;
} else {
result_bytes = text_s - BLOCK_BYTES;
}
if (result_bytes <= 0) {
return 0;
}
char* result = malloc(result_bytes);
// twofish - make nonce (~IV) for CTR mode
const char* nonce;
const char* input; // points to first block of data
char* output; // points to first block of data
int normal_blocks;
if (encr) {
char* nonce_mut = result;
nonce = nonce_mut;
get_random_bytes(nonce_mut, BLOCK_BYTES);
input = text;
output = result + BLOCK_BYTES;
normal_blocks = text_s / BLOCK_BYTES;
} else {
nonce = text;
input = text + BLOCK_BYTES;
output = result;
normal_blocks = (text_s / BLOCK_BYTES) - 1;
}
int i;
for (i = 0; i < normal_blocks; i++) {
const char* b_in = input + i * BLOCK_BYTES;
char* b_out = output + i * BLOCK_BYTES;
memcpy(b_out, nonce, BLOCK_BYTES);
xor_ctr(b_out, i);
encrypt(K, QF, b_out);
xor_block(b_out, b_in, BLOCK_BYTES);
}
int last_block_size = text_s % BLOCK_BYTES;
if (last_block_size) {
const char* b_in = input + normal_blocks * BLOCK_BYTES;
char* b_out = output + normal_blocks * BLOCK_BYTES;
char block[BLOCK_BYTES];
memcpy(block, nonce, BLOCK_BYTES);
xor_ctr(block, normal_blocks);
encrypt(K, QF, block);
memcpy(b_out, block, last_block_size);
xor_block(b_out, b_in, last_block_size);
}
lua_pushlstring(L, result, result_bytes);
free(result);
return 1;
}
static int twofish_encrypt(lua_State *L) {
return twofish_twoways(L, 1);
}
static int twofish_decrypt(lua_State *L) {
return twofish_twoways(L, 0);
}
static int lua_calc_sha256(lua_State *L) {
if (lua_gettop(L) != 1) {
return 0;
}
if (lua_type(L, 1) != LUA_TSTRING) {
return 0;
}
size_t size;
const char* text = lua_tolstring(L, 1, &size);
unsigned char sha256sum[32];
calc_sha256(sha256sum, text, size);
lua_pushlstring(L, sha256sum, 32);
return 1;
}