luci-app-mwan3: add dependecy to size option
[project/luci.git] / libs / luci-lib-px5g / src / px5g.c
1 /*
2  * px5g - Embedded x509 key and certificate generator based on PolarSSL
3  *
4  *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License, version 2.1 as published by the Free Software Foundation.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  *  MA  02110-1301  USA
19  */
20
21 #include "px5g.h"
22 #include <time.h>
23 #include <string.h>
24 #define VERSION 0.1
25
26 static char *xfields[] = {"CN", "O", "C", "OU", "ST", "L", "R"};
27
28 static int px5g_genkey(lua_State *L) {
29         int keysize = luaL_checkint(L, 1), pexp = luaL_optint(L, 2, 65537), ret;
30         px5g_rsa *px5g = lua_newuserdata(L, sizeof(px5g_rsa));
31         if (!px5g) {
32                 return luaL_error(L, "out of memory");
33         }
34
35         px5g->stat = 1;
36         havege_init(&px5g->hs);
37         rsa_init(&px5g->rsa, RSA_PKCS_V15, 0, havege_rand, &px5g->hs);
38
39         if ((ret = rsa_gen_key(&px5g->rsa, keysize, pexp))) {
40                 lua_pushnil(L);
41                 lua_pushinteger(L, ret);
42                 return 2;
43         }
44
45         luaL_getmetatable(L, PX5G_KEY_META);
46         lua_setmetatable(L, -2);
47         return 1;
48 }
49
50 static int px5g_rsa_asn1(lua_State *L) {
51         int ret;
52         px5g_rsa *px5g = luaL_checkudata(L, 1, PX5G_KEY_META);
53         x509_node node;
54
55         x509write_init_node(&node);
56         if ((ret = x509write_serialize_key(&px5g->rsa, &node))) {
57                 x509write_free_node(&node);
58                 lua_pushnil(L);
59                 lua_pushinteger(L, ret);
60                 return 2;
61         }
62
63         lua_pushlstring(L, (char*)node.data, node.len);
64         x509write_free_node(&node);
65         return 1;
66 }
67
68 static int px5g_rsa_create_selfsigned(lua_State *L) {
69         px5g_rsa *px5g = luaL_checkudata(L, 1, PX5G_KEY_META);
70         luaL_checktype(L, 2, LUA_TTABLE);
71         time_t from = (time_t)luaL_checknumber(L, 3);
72         time_t to = (time_t)luaL_checknumber(L, 4);
73         char fstr[20], tstr[20];
74
75         lua_pushliteral(L, "CN");
76         lua_rawget(L, 2);
77         luaL_argcheck(L, lua_isstring(L, -1), 2, "CN missing");
78         lua_pop(L, 1);
79
80         luaL_argcheck(L,
81                 strftime(fstr, sizeof(fstr), "%F %H:%M:%S", gmtime(&from)),
82         3, "Invalid Time");
83
84         luaL_argcheck(L,
85                 strftime(tstr, sizeof(tstr), "%F %H:%M:%S", gmtime(&to)),
86         4, "Invalid Time");
87
88         size_t join = 1;
89         lua_pushliteral(L, "");
90         for (int i = 0; i < (sizeof(xfields) / sizeof(*xfields)); i++) {
91                 lua_pushstring(L, xfields[i]);
92                 lua_rawget(L, 2);
93                 if (lua_isstring(L, -1)) {
94                         const char *val = lua_tostring(L, -1);
95                         luaL_argcheck(L, !strchr(val, ';'), 2, "Invalid Value");
96                         lua_pushfstring(L, "%s=%s;", xfields[i], val);
97                         lua_remove(L, -2);
98                         join++;
99                 } else {
100                         lua_pop(L, 1);
101                 }
102         }
103         lua_concat(L, join);
104
105         x509_raw cert;
106         x509write_init_raw(&cert);
107         x509write_add_pubkey(&cert, &px5g->rsa);
108         x509write_add_subject(&cert, (unsigned char*)lua_tostring(L, -1));
109         x509write_add_validity(&cert, (unsigned char*)fstr, (unsigned char*)tstr);
110         x509write_create_selfsign(&cert, &px5g->rsa);
111
112         lua_pushlstring(L, (char*)cert.raw.data, cert.raw.len);
113         x509write_free_raw(&cert);
114         return 1;
115 }
116
117 static int px5g_rsa__gc(lua_State *L) {
118         px5g_rsa *px5g = luaL_checkudata(L, 1, PX5G_KEY_META);
119         if (px5g->stat) {
120                 rsa_free(&px5g->rsa);
121                 px5g->stat = 0;
122         }
123         return 0;
124 }
125
126 static int px5g_rsa__tostring(lua_State *L) {
127         px5g_rsa *px5g = luaL_checkudata(L, 1, PX5G_KEY_META);
128         lua_pushfstring(L, "px5g context %p", px5g);
129         return 1;
130 }
131
132 /* method table */
133 static const luaL_reg M[] = {
134         {"asn1",                                px5g_rsa_asn1},
135         {"create_selfsigned",   px5g_rsa_create_selfsigned},
136         {"__gc",                                px5g_rsa__gc},
137         {"__tostring",                  px5g_rsa__tostring},
138         {NULL,                  NULL}
139 };
140
141 /* module table */
142 static const luaL_reg R[] = {
143         {"genkey",              px5g_genkey},
144         {NULL,                  NULL}
145 };
146
147 int luaopen_px5g(lua_State *L) {
148         /* register module */
149         luaL_register(L, "px5g", R);
150
151         /* Meta Table */
152         luaL_newmetatable(L, PX5G_KEY_META);
153         luaL_register(L, NULL, M);
154         lua_pushvalue(L, -1);
155         lua_setfield(L, -2, "__index");
156
157         lua_setfield(L, -2, "meta_key");
158         return 1;
159 }