lmtaeslib.c /size: 3423 b    last modification: 2024-01-16 10:22
1/*
2    See license.txt in the root of this project.
3*/
4
5# include "luametatex.h"
6
7# include <utilcrypt.h>
8
9// AES_HAS_IV AES_INLINE_IV AES_CONTINUE AES_NULL_PADDING
10
11static const uint8_t nulliv[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12
13typedef size_t aes_coder (
14    const void *input,
15    size_t      length,
16    void       *output,
17    const void *key,
18    size_t      keylength,
19    const void *iv,
20    int         flags
21);
22
23/* data key [block] [inline] [padding] */ /* key : 16 24 32 */
24
25/* random_bytes is taken from pplib */
26
27static int aeslib_aux_code(lua_State *L, aes_coder code) {
28    size_t inputlength = 0;
29    const char *input = lua_tolstring(L, 1, &inputlength);
30    if (inputlength) {
31        size_t keylength = 0;
32        const char *key = lua_tolstring(L, 2, &keylength);
33        if (keylength == 16 || keylength == 24 || keylength == 32) {
34            luaL_Buffer buffer;
35            /* always */
36            int flags = 0;
37            /* the same length as input plus optional 16 from iv */
38            char *output = NULL;
39            size_t outputlength = 0;
40            /* this is optional, iv get copied in aes */
41            const uint8_t *iv = NULL;
42            switch (lua_type(L, 3)) {
43                case LUA_TSTRING:
44                    {
45                        size_t ivlength = 0;
46                        iv = (const uint8_t *) lua_tolstring(L, 3, &ivlength);
47                        if (ivlength != 16) {
48                            iv = nulliv;
49                        }
50                        break;
51                    }
52                case LUA_TBOOLEAN:
53                    if (lua_toboolean(L, 3)) {
54                        uint8_t randiv[16];
55                        random_bytes(randiv, 16);
56                        iv = (const uint8_t *) randiv;
57                        break;
58                    }
59                    // fall through
60                default:
61                    iv = nulliv;
62            }
63            if (lua_toboolean(L, 4)) {
64               flags |= AES_INLINE_IV;
65            }
66            if (! lua_toboolean(L, 5)) {
67               flags |= AES_NULL_PADDING;
68            }
69            /* always multiples of 16 and we might have the iv too */
70            output = luaL_buffinitsize(L, &buffer, inputlength + 32);
71            outputlength = code(input, inputlength, output, key, keylength, iv, flags);
72            if (outputlength) {
73                luaL_pushresultsize(&buffer, outputlength);
74                return 1;
75            }
76        } else {
77            luaL_error(L, "aeslib: key of length 16, 24 or 32 expected");
78        }
79    }
80    lua_pushnil(L);
81    return 1;
82}
83
84static int aeslib_encode(lua_State *L) {
85    return aeslib_aux_code(L, &aes_encode_data);
86}
87
88static int aeslib_decode(lua_State *L) {
89    return aeslib_aux_code(L, &aes_decode_data);
90}
91
92static int aeslib_random(lua_State *L) {
93    uint8_t iv[32];
94    int n = (int) luaL_optinteger(L, 1, 16);
95    if (n > 32) {
96        n = 32;
97    }
98    random_bytes(iv, n);
99    lua_pushlstring(L, (const char *) iv, n);
100    return 1;
101}
102
103static struct luaL_Reg aeslib_function_list[] = {
104    /*tex We started out with this: */
105    { "encode", aeslib_encode },
106    { "decode", aeslib_decode },
107    { "random", aeslib_random },
108    { NULL,     NULL          },
109};
110
111int luaopen_aes(lua_State *L) {
112    lua_newtable(L);
113    luaL_setfuncs(L, aeslib_function_list, 0);
114    return 1;
115}
116