summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWilliam Ahern <william@server.local>2013-12-09 20:56:25 -0800
committerWilliam Ahern <william@server.local>2013-12-09 20:56:25 -0800
commitd4aa420319bff15a6f84f679c6374dda7cf1b0f2 (patch)
treeb716502f27733e5dd9d2e45715a00bf88586e12e /src
parente42cc7815ff3c948c4ab4e2782da2a2cb4f476bf (diff)
downloadluaossl-d4aa420319bff15a6f84f679c6374dda7cf1b0f2.tar.gz
luaossl-d4aa420319bff15a6f84f679c6374dda7cf1b0f2.tar.bz2
luaossl-d4aa420319bff15a6f84f679c6374dda7cf1b0f2.zip
move newly split files into src/ directory
Diffstat (limited to 'src')
-rw-r--r--src/GNUmakefile214
-rw-r--r--src/Makefile7
-rw-r--r--src/compat52.h152
-rw-r--r--src/openssl.bignum.lua3
-rw-r--r--src/openssl.c3929
-rw-r--r--src/openssl.cipher.lua3
-rw-r--r--src/openssl.digest.lua3
-rw-r--r--src/openssl.hmac.lua3
-rw-r--r--src/openssl.pubkey.lua4
-rw-r--r--src/openssl.rand.lua3
-rw-r--r--src/openssl.ssl.context.lua3
-rw-r--r--src/openssl.ssl.lua3
-rw-r--r--src/openssl.x509.altname.lua13
-rw-r--r--src/openssl.x509.chain.lua3
-rw-r--r--src/openssl.x509.lua3
-rw-r--r--src/openssl.x509.name.lua13
-rw-r--r--src/openssl.x509.store.lua3
17 files changed, 4362 insertions, 0 deletions
diff --git a/src/GNUmakefile b/src/GNUmakefile
new file mode 100644
index 0000000..fcf79a6
--- /dev/null
+++ b/src/GNUmakefile
@@ -0,0 +1,214 @@
1# non-recursive prologue
2sp := $(sp).x
3dirstack_$(sp) := $(d)
4d := $(abspath $(lastword $(MAKEFILE_LIST))/..)
5
6ifeq ($(origin GUARD_$(d)), undefined)
7GUARD_$(d) := 1
8
9
10#
11# E N V I R O N M E N T C O N F I G U R A T I O N
12#
13include $(d)/../GNUmakefile
14
15
16#
17# C O M P I L A T I O N F L A G S
18#
19OS_$(d) = $(shell $(d)/../mk/vendor.os)
20CC_$(d) = $(shell $(d)/../mk/vendor.cc)
21LUAPATH_$(d) = $(shell env CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" $(<D)/../mk/lua.path -krxm3 -I$(DESTDIR)$(includedir) -I/usr/include -I/usr/local/include -P$(DESTDIR)$(bindir) -P$(bindir) -L$(DESTDIR)$(libdir) -L$(libdir) -v$(1) $(2))
22
23CPPFLAGS_$(d) = $(CPPFLAGS_$(abspath $(@D)/../..))
24CFLAGS_$(d) = $(CFLAGS_$(abspath $(@D)/../..))
25LDFLAGS_$(d) = $(LDFLAGS_$(abspath $(@D)/../..))
26SOFLAGS_$(d) = $(SOFLAGS_$(abspath $(@D)/../..))
27
28ifeq ($(CC_$(d)), sunpro)
29CPPFLAGS_$(d) += -DOPENSSL_NO_EC
30endif
31
32LDFLAGS_$(d) += -lssl -lcrypto
33
34#
35# C O M P I L A T I O N R U L E S
36#
37
38define BUILD_$(d)
39
40.SECONDARY: liblua$(1)-openssl openssl$(1)
41
42$$(d)/$(1)/openssl.so: $$(d)/$(1)/openssl.o
43 $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(SOFLAGS) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS)
44
45$$(d)/$(1)/openssl.o: $$(d)/openssl.c $$(d)/compat52.h
46 test "$$(notdir $$(@D))" = "$$(call LUAPATH_$$(<D), $$(notdir $$(@D)), version)"
47 $$(MKDIR) -p $$(@D)
48 $$(CC) $$(CFLAGS_$$(<D)) $$(CFLAGS) $$(call LUAPATH_$$(<D), $$(notdir $$(@D)), cppflags) $$(CPPFLAGS_$$(<D)) $$(CPPFLAGS) -c -o $$@ $$<
49
50liblua$(1)-openssl openssl$(1): $$(d)/$(1)/openssl.so
51
52endef # BUILD_$(d)
53
54$(eval $(call BUILD_$(d),5.1))
55
56$(eval $(call BUILD_$(d),5.2))
57
58ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
59.SECONDARY: all5.1 all5.2 all
60
61all5.1: liblua5.1-openssl
62
63all5.2: liblua5.2-openssl
64
65all: all5.1 all5.2
66
67endif
68
69
70#
71# I N S T A L L & U N I N S T A L L R U L E S
72#
73define INSTALL_$(d)
74
75LUAC$(1)_$(d) = $$(or $$(call LUAPATH_$(d), $(1), luac), true)
76
77MODS$(1)_$(d) = \
78 $$(DESTDIR)$(2)/_openssl.so \
79 $$(DESTDIR)$(3)/openssl/bignum.lua \
80 $$(DESTDIR)$(3)/openssl/pubkey.lua \
81 $$(DESTDIR)$(3)/openssl/x509.lua \
82 $$(DESTDIR)$(3)/openssl/x509/name.lua \
83 $$(DESTDIR)$(3)/openssl/x509/altname.lua \
84 $$(DESTDIR)$(3)/openssl/x509/chain.lua \
85 $$(DESTDIR)$(3)/openssl/x509/store.lua \
86 $$(DESTDIR)$(3)/openssl/ssl/context.lua \
87 $$(DESTDIR)$(3)/openssl/ssl.lua \
88 $$(DESTDIR)$(3)/openssl/digest.lua \
89 $$(DESTDIR)$(3)/openssl/hmac.lua \
90 $$(DESTDIR)$(3)/openssl/cipher.lua \
91 $$(DESTDIR)$(3)/openssl/rand.lua
92
93.SECONDARY: liblua$(1)-openssl-install openssl$(1)-install
94
95$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so
96 $$(MKDIR) -p $$(@D)
97 $$(CP) -p $$< $$@
98
99$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua
100 $$(LUAC$(1)_$(d)) -p $$<
101 $$(MKDIR) -p $$(@D)
102 $$(CP) -p $$< $$@
103
104$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/openssl.x509.%.lua
105 $$(LUAC$(1)_$(d)) -p $$<
106 $$(MKDIR) -p $$(@D)
107 $$(CP) -p $$< $$@
108
109$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua
110 $$(LUAC$(1)_$(d)) -p $$<
111 $$(MKDIR) -p $$(@D)
112 $$(CP) -p $$< $$@
113
114$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua
115 $$(LUAC$(1)_$(d)) -p $$<
116 $$(MKDIR) -p $$(@D)
117 $$(CP) -p $$< $$@
118
119liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d))
120
121.PHONY: liblua$(1)-openssl-uninstall openssl$(1)-uninstall
122
123liblua$(1)-openssl-uninstall openssl$(1)-uninstall:
124 $$(RM) -f $$(MODS$(1)_$(d))
125 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509
126 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl
127 -$$(RMDIR) $$(DESTDIR)$(3)/openssl
128
129endef # INSTALL_$(d)
130
131$(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path)))
132
133$(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path)))
134
135ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
136.SECONDARY: install5.1 install5.2 install
137
138install5.1: liblua5.1-openssl-install
139
140install5.2: liblua5.2-openssl-install
141
142install: install5.1 install5.2
143
144.PHONY: uninstall5.1 uninstall5.2 uninstall
145
146uninstall5.1: liblua5.1-openssl-uninstall
147
148uninstall5.2: liblua5.2-openssl-uninstall
149
150uninstall: uninstall5.1 uninstall5.2
151
152endif
153
154
155#
156# C L E A N R U L E S
157#
158.PHONY: $(d)/clean $(d)/clean~ clean clean~
159
160$(d)/clean:
161 $(RM) -fr $(@D)/*.so $(@D)/*.o $(@D)/*.dSYM $(@D)/5.1 $(@D)/5.2
162
163$(d)/clean~: $(d)/clean
164 $(RM) -f $(@D)/*~
165
166clean: $(d)/clean
167
168clean~: $(d)/clean~
169
170
171#
172# H E L P R U L E S
173#
174.PHONY: $(d)/help help
175
176$(d)/help:
177 @echo
178 @echo "ext/ targets:"
179 @echo ""
180 @echo " all - build all binary targets"
181 @echo "openssl - invokes openssl5.1 and openssl5.2"
182 @echo "openssl5.1 - build 5.1/openssl.so"
183 @echo "openssl5.2 - build 5.2/openssl.so"
184 @echo "install - invokes install5.1 and install5.2"
185 @echo "install5.1 - install openssl Lua 5.1 modules"
186 @echo "install5.2 - install openssl Lua 5.2 modules"
187 @echo "uninstall - invokes uninstall5.1 and uninstall5.2"
188 @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules"
189 @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules"
190 @echo " clean - rm binary targets, object files, debugging symbols, etc"
191 @echo " clean~ - clean + rm *~"
192 @echo " help - echo this help message"
193 @echo ""
194 @echo "Some important Make variables:"
195 @echo ""
196 @echo " prefix - path to install root"
197 @echo ' lua51path - install path for Lua 5.1 modules ($$(lua51path))'
198 @echo 'lua51cpath - install path for Lua 5.1 C modules ($$(lua51cpath))'
199 @echo ' lua52path - install path for Lua 5.1 modules ($$(lua51path))'
200 @echo 'lua52cpath - install path for Lua 5.1 C modules ($$(lua51cpath))'
201 @echo ""
202 @echo "(NOTE: all the common GNU-style paths are supported, including"
203 @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)"
204 @echo ""
205 @echo "Report bugs to <william@25thandClement.com>"
206
207help: $(d)/help
208
209
210endif # include guard
211
212# non-recursive epilogue
213d := $(dirstack_$(sp))
214sp := $(basename $(sp))
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..d0f0d47
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,7 @@
1.POSIX:
2
3all:
4 +gmake -f GNUmakefile all
5
6.DEFAULT:
7 +gmake -f GNUmakefile $<
diff --git a/src/compat52.h b/src/compat52.h
new file mode 100644
index 0000000..96ec9b2
--- /dev/null
+++ b/src/compat52.h
@@ -0,0 +1,152 @@
1/* ==========================================================================
2 * compat52.h - Routines for Lua 5.2 compatibility
3 * --------------------------------------------------------------------------
4 * Copyright (c) 2012 William Ahern
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to permit
11 * persons to whom the Software is furnished to do so, subject to the
12 * following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * ==========================================================================
25 */
26#if LUA_VERSION_NUM < 502
27
28#define LUA_OK 0
29
30
31static void luaL_setmetatable(lua_State *L, const char *tname) {
32 luaL_getmetatable(L, tname);
33 lua_setmetatable(L, -2);
34} /* luaL_setmetatable() */
35
36
37static int lua_absindex(lua_State *L, int idx) {
38 return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
39} /* lua_absindex() */
40
41
42static void *luaL_testudata(lua_State *L, int arg, const char *tname) {
43 void *p = lua_touserdata(L, arg);
44 int eq;
45
46 if (!p || !lua_getmetatable(L, arg))
47 return 0;
48
49 luaL_getmetatable(L, tname);
50 eq = lua_rawequal(L, -2, -1);
51 lua_pop(L, 2);
52
53 return (eq)? p : 0;
54} /* luaL_testudate() */
55
56
57static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
58 int i, t = lua_absindex(L, -1 - nup);
59
60 for (; l->name; l++) {
61 for (i = 0; i < nup; i++)
62 lua_pushvalue(L, -nup);
63 lua_pushcclosure(L, l->func, nup);
64 lua_setfield(L, t, l->name);
65 }
66
67 lua_pop(L, nup);
68} /* luaL_setfuncs() */
69
70
71#define luaL_newlibtable(L, l) \
72 lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
73
74#define luaL_newlib(L, l) \
75 (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
76
77
78static void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) {
79 lua_pushcfunction(L, openf);
80 lua_pushstring(L, modname);
81 lua_call(L, 1, 1);
82
83 lua_getglobal(L, "package");
84 lua_getfield(L, -1, "loaded");
85 lua_pushvalue(L, -3);
86 lua_setfield(L, -2, modname);
87
88 lua_pop(L, 2);
89
90 if (glb) {
91 lua_pushvalue(L, -1);
92 lua_setglobal(L, modname);
93 }
94} /* luaL_requiref() */
95
96
97#define lua_resume(L, from, nargs) lua_resume((L), (nargs))
98
99
100static void lua_rawgetp(lua_State *L, int index, const void *p) {
101 index = lua_absindex(L, index);
102 lua_pushlightuserdata(L, (void *)p);
103 lua_rawget(L, index);
104} /* lua_rawgetp() */
105
106static void lua_rawsetp(lua_State *L, int index, const void *p) {
107 index = lua_absindex(L, index);
108 lua_pushlightuserdata(L, (void *)p);
109 lua_pushvalue(L, -2);
110 lua_rawset(L, index);
111 lua_pop(L, 1);
112} /* lua_rawsetp() */
113
114
115#ifndef LUA_UNSIGNED
116#define LUA_UNSIGNED unsigned
117#endif
118
119typedef LUA_UNSIGNED lua_Unsigned;
120
121
122static void lua_pushunsigned(lua_State *L, lua_Unsigned n) {
123 lua_pushnumber(L, (lua_Number)n);
124} /* lua_pushunsigned() */
125
126static lua_Unsigned luaL_checkunsigned(lua_State *L, int arg) {
127 return (lua_Unsigned)luaL_checknumber(L, arg);
128} /* luaL_checkunsigned() */
129
130
131static lua_Unsigned luaL_optunsigned(lua_State *L, int arg, lua_Unsigned def) {
132 return (lua_Unsigned)luaL_optnumber(L, arg, (lua_Number)def);
133} /* luaL_optunsigned() */
134
135
136#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */
137#define LUA_FILEHANDLE "FILE*"
138#endif
139
140/*
141 * Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the
142 * first member a FILE *, similar to Lua 5.2.
143 */
144typedef struct luaL_Stream {
145 FILE *f;
146} luaL_Stream;
147
148
149#define lua_rawlen(...) lua_objlen(__VA_ARGS__)
150
151
152#endif /* LUA_VERSION_NUM < 502 */
diff --git a/src/openssl.bignum.lua b/src/openssl.bignum.lua
new file mode 100644
index 0000000..3090a68
--- /dev/null
+++ b/src/openssl.bignum.lua
@@ -0,0 +1,3 @@
1local bignum = require"_openssl.bignum"
2
3return bignum
diff --git a/src/openssl.c b/src/openssl.c
new file mode 100644
index 0000000..c8af43d
--- /dev/null
+++ b/src/openssl.c
@@ -0,0 +1,3929 @@
1/* ==========================================================================
2 * openssl.c - Lua OpenSSL
3 * --------------------------------------------------------------------------
4 * Copyright (c) 2012 William Ahern
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to permit
11 * persons to whom the Software is furnished to do so, subject to the
12 * following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * ==========================================================================
25 */
26#ifndef L_OPENSSL_H
27#define L_OPENSSH_H
28
29#include <limits.h> /* INT_MAX INT_MIN */
30#include <string.h> /* memset(3) */
31#include <strings.h> /* strcasecmp(3) */
32#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */
33#include <time.h> /* struct tm time_t strptime(3) */
34
35#include <sys/types.h>
36#include <sys/stat.h> /* struct stat stat(2) */
37#include <sys/socket.h> /* AF_INET AF_INET6 */
38
39#include <netinet/in.h> /* struct in_addr struct in6_addr */
40#include <arpa/inet.h> /* inet_pton(3) */
41
42#include <openssl/err.h>
43#include <openssl/bn.h>
44#include <openssl/asn1.h>
45#include <openssl/x509.h>
46#include <openssl/x509v3.h>
47#include <openssl/evp.h>
48#include <openssl/pem.h>
49#include <openssl/ssl.h>
50#include <openssl/hmac.h>
51#include <openssl/rand.h>
52
53#include <lua.h>
54#include <lualib.h>
55#include <lauxlib.h>
56
57#if LUA_VERSION_NUM < 502
58#include "compat52.h"
59#endif
60
61#define BIGNUM_CLASS "BIGNUM*"
62#define PUBKEY_CLASS "EVP_PKEY*"
63#define X509_NAME_CLASS "X509_NAME*"
64#define X509_GENS_CLASS "GENERAL_NAMES*"
65#define X509_CERT_CLASS "X509*"
66#define X509_CHAIN_CLASS "STACK_OF(X509)*"
67#define X509_CSR_CLASS "X509_REQ*"
68#define X509_STORE_CLASS "X509_STORE*"
69#define X509_STCTX_CLASS "X509_STORE_CTX*"
70#define SSL_CTX_CLASS "SSL_CTX*"
71#define SSL_CLASS "SSL*"
72#define DIGEST_CLASS "EVP_MD_CTX" /* not a pointer */
73#define HMAC_CLASS "HMAC_CTX" /* not a pointer */
74#define CIPHER_CLASS "EVP_CIPHER_CTX" /* not a pointer */
75
76
77#define countof(a) (sizeof (a) / sizeof *(a))
78#define endof(a) (&(a)[countof(a)])
79
80#define CLAMP(i, min, max) (((i) < (min))? (min) : ((i) > (max))? (max) : (i))
81
82#undef MIN
83#define MIN(a, b) (((a) < (b))? (a) : (b))
84
85#define stricmp(a, b) strcasecmp((a), (b))
86#define strieq(a, b) (!stricmp((a), (b)))
87
88#define SAY_(file, func, line, fmt, ...) \
89 fprintf(stderr, "%s:%d: " fmt "%s", __func__, __LINE__, __VA_ARGS__)
90
91#define SAY(...) SAY_(__FILE__, __func__, __LINE__, __VA_ARGS__, "\n")
92
93#define HAI SAY("hai")
94
95
96static void *prepudata(lua_State *L, size_t size, const char *tname, int (*gc)(lua_State *)) {
97 void *p = memset(lua_newuserdata(L, size), 0, size);
98
99 if (tname) {
100 luaL_setmetatable(L, tname);
101 } else {
102 lua_newtable(L);
103 lua_pushcfunction(L, gc);
104 lua_setfield(L, -2, "__gc");
105 lua_setmetatable(L, -2);
106 }
107
108 return p;
109} /* prepudata() */
110
111
112static void *prepsimple(lua_State *L, const char *tname, int (*gc)(lua_State *)) {
113 void **p = prepudata(L, sizeof (void *), tname, gc);
114 return p;
115} /* prepsimple() */
116
117#define prepsimple_(a, b, c, ...) prepsimple((a), (b), (c))
118#define prepsimple(...) prepsimple_(__VA_ARGS__, 0)
119
120
121static void *checksimple(lua_State *L, int index, const char *tname) {
122 void **p;
123
124 if (tname) {
125 p = luaL_checkudata(L, index, tname);
126 } else {
127 luaL_checktype(L, index, LUA_TUSERDATA);
128 p = lua_touserdata(L, index);
129 }
130
131 return *p;
132} /* checksimple() */
133
134
135static void *testsimple(lua_State *L, int index, const char *tname) {
136 void **p;
137
138 if (tname) {
139 p = luaL_testudata(L, index, tname);
140 } else {
141 luaL_checktype(L, index, LUA_TUSERDATA);
142 p = lua_touserdata(L, index);
143 }
144
145 return (p)? *p : (void *)0;
146} /* testsimple() */
147
148
149static const char *pusherror(lua_State *L, const char *fun) {
150 unsigned long code;
151 const char *path, *file;
152 int line;
153 char txt[256];
154
155 code = ERR_get_error_line(&path, &line);
156
157 if ((file = strrchr(path, '/')))
158 ++file;
159 else
160 file = path;
161
162 ERR_clear_error();
163
164 ERR_error_string_n(code, txt, sizeof txt);
165
166 if (fun)
167 return lua_pushfstring(L, "%s: %s:%d:%s", fun, file, line, txt);
168 else
169 return lua_pushfstring(L, "%s:%d:%s", file, line, txt);
170} /* pusherror() */
171
172
173static int throwssl(lua_State *L, const char *fun) {
174 pusherror(L, fun);
175
176 return lua_error(L);
177} /* throwssl() */
178
179
180static int interpose(lua_State *L, const char *mt) {
181 luaL_getmetatable(L, mt);
182
183 if (!strncmp("__", luaL_checkstring(L, 1), 2))
184 lua_pushvalue(L, -1);
185 else
186 lua_getfield(L, -1, "__index");
187
188 lua_pushvalue(L, -4); /* push method name */
189 lua_gettable(L, -2); /* push old method */
190
191 lua_pushvalue(L, -5); /* push method name */
192 lua_pushvalue(L, -5); /* push new method */
193 lua_settable(L, -4); /* replace old method */
194
195 return 1; /* return old method */
196} /* interpose() */
197
198
199static void addclass(lua_State *L, const char *name, const luaL_Reg *methods, const luaL_Reg *metamethods) {
200 if (luaL_newmetatable(L, name)) {
201 luaL_setfuncs(L, metamethods, 0);
202 lua_newtable(L);
203 luaL_setfuncs(L, methods, 0);
204 lua_setfield(L, -2, "__index");
205 lua_pop(L, 1);
206 }
207} /* addclass() */
208
209
210static int checkoption(struct lua_State *L, int index, const char *def, const char *opts[]) {
211 const char *opt = (def)? luaL_optstring(L, index, def) : luaL_checkstring(L, index);
212 int i;
213
214 for (i = 0; opts[i]; i++) {
215 if (strieq(opts[i], opt))
216 return i;
217 }
218
219 return luaL_argerror(L, index, lua_pushfstring(L, "invalid option %s", opt));
220} /* checkoption() */
221
222
223static _Bool getfield(lua_State *L, int index, const char *k) {
224 lua_getfield(L, index, k);
225
226 if (lua_isnil(L, -1)) {
227 lua_pop(L, 1);
228
229 return 0;
230 } else {
231 return 1;
232 }
233} /* getfield() */
234
235
236static _Bool loadfield(lua_State *L, int index, const char *k, int type, void *p) {
237 if (!getfield(L, index, k))
238 return 0;
239
240 switch (type) {
241 case LUA_TSTRING:
242 *(const char **)p = luaL_checkstring(L, -1);
243 break;
244 case LUA_TNUMBER:
245 *(lua_Number *)p = luaL_checknumber(L, -1);
246 break;
247 default:
248 luaL_error(L, "loadfield(type=%d): invalid type", type);
249 break;
250 } /* switch() */
251
252 lua_pop(L, 1); /* table keeps reference */
253
254 return 1;
255} /* loadfield() */
256
257
258static const char *pushnid(lua_State *L, int nid) {
259 const char *txt;
260 ASN1_OBJECT *obj;
261 char buf[256];
262 int len;
263
264 if ((txt = OBJ_nid2sn(nid)) || (txt = OBJ_nid2ln(nid))) {
265 lua_pushstring(L, txt);
266 } else {
267 if (!(obj = OBJ_nid2obj(nid)))
268 luaL_error(L, "%d: unknown ASN.1 NID", nid);
269
270 if (-1 == (len = OBJ_obj2txt(buf, sizeof buf, obj, 1)))
271 luaL_error(L, "%d: invalid ASN.1 NID", nid);
272
273 lua_pushlstring(L, buf, len);
274 }
275
276 return lua_tostring(L, -1);
277} /* pushnid() */
278
279
280static void initall(lua_State *L);
281
282
283/*
284 * BIGNUM - openssl.bignum
285 *
286 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
287
288static BIGNUM *bn_push(lua_State *L) {
289 BIGNUM **ud = prepsimple(L, BIGNUM_CLASS);
290
291 if (!(*ud = BN_new()))
292 throwssl(L, "bignum.new");
293
294 return *ud;
295} /* bn_push() */
296
297
298#define checkbig_(a, b, c, ...) checkbig((a), (b), (c))
299#define checkbig(...) checkbig_(__VA_ARGS__, &(_Bool){ 0 })
300
301static BIGNUM *(checkbig)(lua_State *, int, _Bool *);
302
303static int bn_new(lua_State *L) {
304 int i, n;
305
306 if ((n = lua_gettop(L)) > 0) {
307 for (i = 1; i <= n; i++)
308 checkbig(L, i);
309
310 return n;
311 } else {
312 bn_push(L);
313
314 return 1;
315 }
316} /* bn_new() */
317
318
319static int bn_interpose(lua_State *L) {
320 return interpose(L, BIGNUM_CLASS);
321} /* bn_interpose() */
322
323
324/* return integral part */
325static inline double intof(double f) {
326 return (isfinite(f))? floor(fabs(f)) : 0.0;
327} /* intof() */
328
329
330/* convert integral to BN_ULONG. returns success or failure. */
331static _Bool int2ul(BN_ULONG *ul, double f) {
332 int exp;
333
334 frexp(f, &exp);
335
336 if (exp > (int)sizeof *ul * 8)
337 return 0;
338
339 *ul = (BN_ULONG)f;
340
341 return 1;
342} /* int2ul() */
343
344
345/* convert integral BIGNUM. returns success or failure. */
346static _Bool int2bn(BIGNUM **bn, double q) {
347 unsigned char nib[32], bin[32], *p;
348 size_t i, n;
349 double r;
350
351 p = nib;
352
353 while (q >= 1.0 && p < endof(nib)) {
354 r = fmod(q, 256.0);
355 *p++ = r;
356 q = round((q - r) / 256.0);
357 }
358
359 n = p - nib;
360
361 for (i = 0; i < n; i++) {
362 bin[i] = *--p;
363 }
364
365 if (!(*bn = BN_bin2bn(bin, n, *bn)))
366 return 0;
367
368 return 1;
369} /* int2bn() */
370
371
372/* convert double to BIGNUM. returns success or failure. */
373static _Bool f2bn(BIGNUM **bn, double f) {
374 double i = intof(f);
375 BN_ULONG lu;
376
377 if (int2ul(&lu, i)) {
378 if (!*bn && !(*bn = BN_new()))
379 return 0;
380
381 if (!BN_set_word(*bn, lu))
382 return 0;
383 } else if (!int2bn(bn, i))
384 return 0;
385
386 BN_set_negative(*bn, signbit(f));
387
388 return 1;
389} /* f2bn() */
390
391
392static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
393 BIGNUM **bn;
394 const char *dec;
395 size_t len;
396
397 index = lua_absindex(L, index);
398
399 switch (lua_type(L, index)) {
400 case LUA_TSTRING:
401 *lvalue = 0;
402
403 dec = lua_tolstring(L, index, &len);
404
405 luaL_argcheck(L, len > 0 && *dec, index, "invalid big number string");
406
407 bn = prepsimple(L, BIGNUM_CLASS);
408
409 if (!BN_dec2bn(bn, dec))
410 throwssl(L, "bignum");
411
412 lua_replace(L, index);
413
414 return *bn;
415 case LUA_TNUMBER:
416 *lvalue = 0;
417
418 bn = prepsimple(L, BIGNUM_CLASS);
419
420 if (!f2bn(bn, lua_tonumber(L, index)))
421 throwssl(L, "bignum");
422
423 lua_replace(L, index);
424
425 return *bn;
426 default:
427 *lvalue = 1;
428
429 return checksimple(L, index, BIGNUM_CLASS);
430 } /* switch() */
431} /* checkbig() */
432
433
434static void bn_prepops(lua_State *L, BIGNUM **r, BIGNUM **a, BIGNUM **b, _Bool commute) {
435 _Bool lvalue = 1;
436
437 lua_settop(L, 2); /* a, b */
438
439 *a = checkbig(L, 1, &lvalue);
440
441 if (!lvalue && commute)
442 lua_pushvalue(L, 1);
443
444 *b = checkbig(L, 2, &lvalue);
445
446 if (!lvalue && commute && lua_gettop(L) < 3)
447 lua_pushvalue(L, 2);
448
449 if (lua_gettop(L) < 3)
450 bn_push(L);
451
452 *r = *(BIGNUM **)lua_touserdata(L, 3);
453} /* bn_prepops() */
454
455
456static int ctx__gc(lua_State *L) {
457 BN_CTX **ctx = lua_touserdata(L, 1);
458
459 BN_CTX_free(*ctx);
460 *ctx = NULL;
461
462 return 0;
463} /* ctx__gc() */
464
465static BN_CTX *getctx(lua_State *L) {
466 BN_CTX **ctx;
467
468 lua_pushcfunction(L, &ctx__gc);
469 lua_gettable(L, LUA_REGISTRYINDEX);
470
471 if (lua_isnil(L, -1)) {
472 lua_pop(L, 1);
473
474 ctx = prepsimple(L, NULL, &ctx__gc);
475
476 if (!(*ctx = BN_CTX_new()))
477 throwssl(L, "bignum");
478
479 lua_pushcfunction(L, &ctx__gc);
480 lua_pushvalue(L, -2);
481 lua_settable(L, LUA_REGISTRYINDEX);
482 }
483
484 ctx = lua_touserdata(L, -1);
485 lua_pop(L, 1);
486
487 return *ctx;
488} /* getctx() */
489
490
491static int bn__add(lua_State *L) {
492 BIGNUM *r, *a, *b;
493
494 bn_prepops(L, &r, &a, &b, 1);
495
496 if (!BN_add(r, a, b))
497 return throwssl(L, "bignum:__add");
498
499 return 1;
500} /* bn__add() */
501
502
503static int bn__sub(lua_State *L) {
504 BIGNUM *r, *a, *b;
505
506 bn_prepops(L, &r, &a, &b, 0);
507
508 if (!BN_sub(r, a, b))
509 return throwssl(L, "bignum:__sub");
510
511 return 1;
512} /* bn__sub() */
513
514
515static int bn__mul(lua_State *L) {
516 BIGNUM *r, *a, *b;
517
518 bn_prepops(L, &r, &a, &b, 1);
519
520 if (!BN_mul(r, a, b, getctx(L)))
521 return throwssl(L, "bignum:__mul");
522
523 return 1;
524} /* bn__mul() */
525
526
527static int bn__div(lua_State *L) {
528 BIGNUM *r, *a, *b;
529 BN_CTX *ctx;
530
531 bn_prepops(L, &r, &a, &b, 0);
532
533 if (!BN_div(r, NULL, a, b, getctx(L)))
534 return throwssl(L, "bignum:__div");
535
536 return 1;
537} /* bn__div() */
538
539
540static int bn__mod(lua_State *L) {
541 BIGNUM *r, *a, *b;
542 BN_CTX *ctx;
543
544 bn_prepops(L, &r, &a, &b, 0);
545
546 if (!BN_mod(r, a, b, getctx(L)))
547 return throwssl(L, "bignum:__mod");
548
549 return 1;
550} /* bn__mod() */
551
552
553static int bn__pow(lua_State *L) {
554 BIGNUM *r, *a, *b;
555 BN_CTX *ctx;
556
557 bn_prepops(L, &r, &a, &b, 0);
558
559 if (!BN_exp(r, a, b, getctx(L)))
560 return throwssl(L, "bignum:__pow");
561
562 return 1;
563} /* bn__pow() */
564
565
566static int bn__unm(lua_State *L) {
567 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
568
569 BN_set_negative(a, !BN_is_negative(a));
570
571 return 1;
572} /* bn__unm() */
573
574
575static int bn__eq(lua_State *L) {
576 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
577 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
578
579 lua_pushboolean(L, 0 == BN_cmp(a, b));
580
581 return 1;
582} /* bn__eq() */
583
584
585static int bn__lt(lua_State *L) {
586 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
587 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
588 int cmp = BN_cmp(a, b);
589
590 lua_pushboolean(L, cmp == -1);
591
592 return 1;
593} /* bn__lt() */
594
595
596static int bn__le(lua_State *L) {
597 BIGNUM *a = checksimple(L, 1, BIGNUM_CLASS);
598 BIGNUM *b = checksimple(L, 2, BIGNUM_CLASS);
599 int cmp = BN_cmp(a, b);
600
601 lua_pushboolean(L, cmp <= 0);
602
603 return 1;
604} /* bn__le() */
605
606
607static int bn__gc(lua_State *L) {
608 BIGNUM **ud = luaL_checkudata(L, 1, BIGNUM_CLASS);
609
610 BN_free(*ud);
611 *ud = NULL;
612
613 return 0;
614} /* bn__gc() */
615
616
617static int bn__tostring(lua_State *L) {
618 BIGNUM *bn = checksimple(L, 1, BIGNUM_CLASS);
619 char *txt;
620
621 if (!(txt = BN_bn2dec(bn)))
622 throwssl(L, "bignum:__tostring");
623
624 lua_pushstring(L, txt);
625
626 return 1;
627} /* bn__tostring() */
628
629
630static const luaL_Reg bn_methods[] = {
631 { NULL, NULL },
632};
633
634static const luaL_Reg bn_metatable[] = {
635 { "__add", &bn__add },
636 { "__sub", &bn__sub },
637 { "__mul", &bn__mul },
638 { "__div", &bn__div },
639 { "__mod", &bn__mod },
640 { "__pow", &bn__pow },
641 { "__unm", &bn__unm },
642 { "__eq", &bn__eq },
643 { "__lt", &bn__lt },
644 { "__le", &bn__le },
645 { "__gc", &bn__gc },
646 { "__tostring", &bn__tostring },
647 { NULL, NULL },
648};
649
650
651static const luaL_Reg bn_globals[] = {
652 { "new", &bn_new },
653 { "interpose", &bn_interpose },
654 { NULL, NULL },
655};
656
657int luaopen__openssl_bignum(lua_State *L) {
658 initall(L);
659
660 luaL_newlib(L, bn_globals);
661
662 return 1;
663} /* luaopen__openssl_bignum() */
664
665
666/*
667 * EVP_PKEY - openssl.pubkey
668 *
669 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
670
671static int bio__gc(lua_State *L) {
672 BIO **bio = lua_touserdata(L, 1);
673
674 BIO_free(*bio);
675 *bio = NULL;
676
677 return 0;
678} /* bio__gc() */
679
680static BIO *getbio(lua_State *L) {
681 BIO **bio;
682
683 lua_pushcfunction(L, &bio__gc);
684 lua_gettable(L, LUA_REGISTRYINDEX);
685
686 if (lua_isnil(L, -1)) {
687 lua_pop(L, 1);
688
689 bio = prepsimple(L, NULL, &bio__gc);
690
691 if (!(*bio = BIO_new(BIO_s_mem())))
692 throwssl(L, "BIO_new");
693
694 lua_pushcfunction(L, &bio__gc);
695 lua_pushvalue(L, -2);
696 lua_settable(L, LUA_REGISTRYINDEX);
697 }
698
699 bio = lua_touserdata(L, -1);
700 lua_pop(L, 1);
701
702 BIO_reset(*bio);
703
704 return *bio;
705} /* getbio() */
706
707
708static int pk_new(lua_State *L) {
709 EVP_PKEY **ud;
710
711 lua_settop(L, 1);
712
713 ud = prepsimple(L, PUBKEY_CLASS);
714
715 if (lua_istable(L, 1)) {
716 int type = EVP_PKEY_RSA;
717 unsigned bits = 1024;
718 unsigned exp = 65537;
719 int curve = NID_X9_62_prime192v1;
720 const char *id;
721 lua_Number n;
722
723 if (!lua_istable(L, 1))
724 goto creat;
725
726 if (loadfield(L, 1, "type", LUA_TSTRING, &id)) {
727 static const struct { int nid; const char *sn; } types[] = {
728 { EVP_PKEY_RSA, "RSA" },
729 { EVP_PKEY_DSA, "DSA" },
730 { EVP_PKEY_DH, "DH" },
731 { EVP_PKEY_EC, "EC" },
732 };
733 unsigned i;
734
735 type = OBJ_sn2nid(id);
736
737 if (NID_undef == (type = EVP_PKEY_type(OBJ_sn2nid(id)))) {
738 for (i = 0; i < countof(types); i++) {
739 if (strieq(id, types[i].sn)) {
740 type = types[i].nid;
741 break;
742 }
743 }
744 }
745
746 luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id));
747 }
748
749 if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
750 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
751 bits = (unsigned)n;
752 }
753
754 if (loadfield(L, 1, "exp", LUA_TNUMBER, &n)) {
755 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n));
756 exp = (unsigned)n;
757 }
758
759 if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) {
760 curve = OBJ_sn2nid(id);
761 luaL_argcheck(L, curve != NID_undef, 1, lua_pushfstring(L, "%s: invalid curve", id));
762 }
763
764creat:
765 if (!(*ud = EVP_PKEY_new()))
766 return throwssl(L, "pubkey.new");
767
768 switch (EVP_PKEY_type(type)) {
769 case EVP_PKEY_RSA: {
770 RSA *rsa;
771
772 if (!(rsa = RSA_generate_key(bits, exp, 0, 0)))
773 return throwssl(L, "pubkey.new");
774
775 EVP_PKEY_set1_RSA(*ud, rsa);
776
777 RSA_free(rsa);
778
779 break;
780 }
781 case EVP_PKEY_DSA: {
782 DSA *dsa;
783
784 if (!(dsa = DSA_generate_parameters(bits, 0, 0, 0, 0, 0, 0)))
785 return throwssl(L, "pubkey.new");
786
787 if (!DSA_generate_key(dsa)) {
788 DSA_free(dsa);
789 return throwssl(L, "pubkey.new");
790 }
791
792 EVP_PKEY_set1_DSA(*ud, dsa);
793
794 DSA_free(dsa);
795
796 break;
797 }
798 case EVP_PKEY_DH: {
799 DH *dh;
800
801 if (!(dh = DH_generate_parameters(bits, exp, 0, 0)))
802 return throwssl(L, "pubkey.new");
803
804 if (!DH_generate_key(dh)) {
805 DH_free(dh);
806 return throwssl(L, "pubkey.new");
807 }
808
809 EVP_PKEY_set1_DH(*ud, dh);
810
811 DH_free(dh);
812
813 break;
814 }
815#ifndef OPENSSL_NO_EC
816 case EVP_PKEY_EC: {
817 EC_GROUP *grp;
818 EC_KEY *key;
819
820 if (!(grp = EC_GROUP_new_by_curve_name(curve)))
821 return throwssl(L, "pubkey.new");
822
823 EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_NAMED_CURVE);
824
825 /* compressed points patented */
826 EC_GROUP_set_point_conversion_form(grp, POINT_CONVERSION_UNCOMPRESSED);
827
828 if (!(key = EC_KEY_new())) {
829 EC_GROUP_free(grp);
830 return throwssl(L, "pubkey.new");
831 }
832
833 EC_KEY_set_group(key, grp);
834
835 EC_GROUP_free(grp);
836
837 if (!EC_KEY_generate_key(key)) {
838 EC_KEY_free(key);
839 return throwssl(L, "pubkey.new");
840 }
841
842 EVP_PKEY_set1_EC_KEY(*ud, key);
843
844 EC_KEY_free(key);
845
846 break;
847 }
848#endif
849 default:
850 return luaL_error(L, "%d: unknown EVP base type (%d)", EVP_PKEY_type(type), type);
851 } /* switch() */
852 } else {
853 const char *pem;
854 size_t len;
855 BIO *bio;
856 int ok;
857
858 if (!(*ud = EVP_PKEY_new()))
859 return throwssl(L, "pubkey.new");
860
861 switch (lua_type(L, 1)) {
862 case LUA_TSTRING:
863 pem = luaL_checklstring(L, 1, &len);
864
865 if (!(bio = BIO_new_mem_buf((void *)pem, len)))
866 return throwssl(L, "pubkey.new");
867
868 if (strstr(pem, "PUBLIC KEY")) {
869 ok = !!PEM_read_bio_PUBKEY(bio, ud, 0, 0);
870 } else {
871 ok = !!PEM_read_bio_PrivateKey(bio, ud, 0, 0);
872 }
873
874 BIO_free(bio);
875
876 if (!ok)
877 return throwssl(L, "pubkey.new");
878
879 break;
880 default:
881 return luaL_error(L, "%s: unknown key initializer", lua_typename(L, lua_type(L, 1)));
882 } /* switch() */
883 }
884
885 return 1;
886} /* pk_new() */
887
888
889static int pk_interpose(lua_State *L) {
890 return interpose(L, X509_NAME_CLASS);
891} /* pk_interpose() */
892
893
894static int pk_type(lua_State *L) {
895 EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
896 int nid = key->type;
897
898 pushnid(L, nid);
899
900 return 1;
901} /* pk_type() */
902
903
904static int pk_setPublicKey(lua_State *L) {
905 EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS);
906 const char *pem;
907 size_t len;
908 BIO *bio;
909 int ok;
910
911 lua_settop(L, 2);
912
913 pem = luaL_checklstring(L, 2, &len);
914
915 if (!(bio = BIO_new_mem_buf((void *)pem, len)))
916 return throwssl(L, "pubkey.new");
917
918 ok = !!PEM_read_bio_PUBKEY(bio, key, 0, 0);
919
920 BIO_free(bio);
921
922 if (!ok)
923 return throwssl(L, "pubkey.new");
924
925 lua_pushboolean(L, 1);
926
927 return 1;
928} /* pk_setPublicKey() */
929
930
931static int pk_setPrivateKey(lua_State *L) {
932 EVP_PKEY **key = luaL_checkudata(L, 1, PUBKEY_CLASS);
933 const char *pem;
934 size_t len;
935 BIO *bio;
936 int ok;
937
938 lua_settop(L, 2);
939
940 pem = luaL_checklstring(L, 2, &len);
941
942 if (!(bio = BIO_new_mem_buf((void *)pem, len)))
943 return throwssl(L, "pubkey.new");
944
945 ok = !!PEM_read_bio_PrivateKey(bio, key, 0, 0);
946
947 BIO_free(bio);
948
949 if (!ok)
950 return throwssl(L, "pubkey.new");
951
952 lua_pushboolean(L, 1);
953
954 return 1;
955} /* pk_setPrivateKEY() */
956
957
958static int pk_sign(lua_State *L) {
959 EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
960 EVP_MD_CTX *md = luaL_checkudata(L, 2, DIGEST_CLASS);
961 luaL_Buffer B;
962 unsigned n;
963
964 if (LUAL_BUFFERSIZE < EVP_PKEY_size(key))
965 return luaL_error(L, "pubkey:sign: LUAL_BUFFERSIZE(%u) < EVP_PKEY_size(%u)", (unsigned)LUAL_BUFFERSIZE, (unsigned)EVP_PKEY_size(key));
966
967 luaL_buffinit(L, &B);
968 n = LUAL_BUFFERSIZE;
969
970 if (!EVP_SignFinal(md, (void *)luaL_prepbuffer(&B), &n, key))
971 return throwssl(L, "pubkey:sign");
972
973 luaL_addsize(&B, n);
974 luaL_pushresult(&B);
975
976 return 1;
977} /* pk_sign() */
978
979
980static int pk_verify(lua_State *L) {
981 EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
982 size_t len;
983 const void *sig = luaL_checklstring(L, 2, &len);
984 EVP_MD_CTX *md = luaL_checkudata(L, 3, DIGEST_CLASS);
985
986 switch (EVP_VerifyFinal(md, sig, len, key)) {
987 case 0: /* WRONG */
988 ERR_clear_error();
989 lua_pushboolean(L, 0);
990
991 break;
992 case 1: /* OK */
993 lua_pushboolean(L, 1);
994
995 break;
996 default:
997 return throwssl(L, "pubkey:verify");
998 }
999
1000 return 1;
1001} /* pk_verify() */
1002
1003
1004static int pk_toPEM(lua_State *L) {
1005 EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
1006 int top, i, ok;
1007 BIO *bio;
1008 char *pem;
1009 long len;
1010
1011 if (1 == (top = lua_gettop(L))) {
1012 lua_pushstring(L, "publickey");
1013 ++top;
1014 }
1015
1016 bio = getbio(L);
1017
1018 for (i = 2; i <= top; i++) {
1019 static const char *opts[] = {
1020 "public", "PublicKey",
1021 "private", "PrivateKey",
1022// "params", "Parameters",
1023 NULL,
1024 };
1025
1026 switch (checkoption(L, i, NULL, opts)) {
1027 case 0: case 1: /* public, PublicKey */
1028 if (!PEM_write_bio_PUBKEY(bio, key))
1029 return throwssl(L, "pubkey:__tostring");
1030
1031 len = BIO_get_mem_data(bio, &pem);
1032 lua_pushlstring(L, pem, len);
1033
1034 BIO_reset(bio);
1035 break;
1036 case 2: case 3: /* private, PrivateKey */
1037 if (!PEM_write_bio_PrivateKey(bio, key, 0, 0, 0, 0, 0))
1038 throwssl(L, "pubkey:__tostring");
1039
1040 len = BIO_get_mem_data(bio, &pem);
1041 lua_pushlstring(L, pem, len);
1042
1043 break;
1044#if 0
1045 case 4: case 5: /* params, Parameters */
1046 /* EVP_PKEY_base_id not in OS X */
1047 switch (EVP_PKEY_type(key->type)) {
1048 case EVP_PKEY_RSA:
1049 break;
1050 case EVP_PKEY_DSA: {
1051 DSA *dsa = EVP_PKEY_get1_DSA(key);
1052
1053 ok = !!PEM_write_bio_DSAparams(bio, dsa);
1054
1055 DSA_free(dsa);
1056
1057 if (!ok)
1058 return throwssl(L, "pubkey:__tostring");
1059
1060 break;
1061 }
1062 case EVP_PKEY_DH: {
1063 DH *dh = EVP_PKEY_get1_DH(key);
1064
1065 ok = !!PEM_write_bio_DHparams(bio, dh);
1066
1067 DH_free(dh);
1068
1069 if (!ok)
1070 return throwssl(L, "pubkey:__tostring");
1071
1072 break;
1073 }
1074#ifndef OPENSSL_NO_EC
1075 case EVP_PKEY_EC: {
1076 EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
1077 const EC_GROUP *grp = EC_KEY_get0_group(ec);
1078
1079 ok = !!PEM_write_bio_ECPKParameters(bio, grp);
1080
1081 EC_KEY_free(ec);
1082
1083 if (!ok)
1084 return throwssl(L, "pubkey:__tostring");
1085
1086 break;
1087 }
1088#endif
1089 default:
1090 return luaL_error(L, "%d: unknown EVP base type", EVP_PKEY_type(key->type));
1091 }
1092
1093 lua_pushlstring(L, pem, len);
1094
1095 BIO_reset(bio);
1096
1097 break;
1098#endif
1099 default:
1100 lua_pushnil(L);
1101
1102 break;
1103 } /* switch() */
1104 } /* for() */
1105
1106 return lua_gettop(L) - top;
1107} /* pk_toPEM() */
1108
1109
1110static int pk__tostring(lua_State *L) {
1111 EVP_PKEY *key = checksimple(L, 1, PUBKEY_CLASS);
1112 BIO *bio = getbio(L);
1113 char *pem;
1114 long len;
1115 int ok;
1116
1117 if (!PEM_write_bio_PUBKEY(bio, key))
1118 return throwssl(L, "pubkey:__tostring");
1119
1120 len = BIO_get_mem_data(bio, &pem);
1121 lua_pushlstring(L, pem, len);
1122
1123 return 1;
1124} /* pk__tostring() */
1125
1126
1127static int pk__gc(lua_State *L) {
1128 EVP_PKEY **ud = luaL_checkudata(L, 1, PUBKEY_CLASS);
1129
1130 EVP_PKEY_free(*ud);
1131 *ud = NULL;
1132
1133 return 0;
1134} /* pk__gc() */
1135
1136
1137static const luaL_Reg pk_methods[] = {
1138 { "type", &pk_type },
1139 { "setPublicKey", &pk_setPublicKey },
1140 { "setPrivateKey", &pk_setPrivateKey },
1141 { "sign", &pk_sign },
1142 { "verify", &pk_verify },
1143 { "toPEM", &pk_toPEM },
1144 { NULL, NULL },
1145};
1146
1147static const luaL_Reg pk_metatable[] = {
1148 { "__tostring", &pk__tostring },
1149 { "__gc", &pk__gc },
1150 { NULL, NULL },
1151};
1152
1153
1154static const luaL_Reg pk_globals[] = {
1155 { "new", &pk_new },
1156 { "interpose", &pk_interpose },
1157 { NULL, NULL },
1158};
1159
1160int luaopen__openssl_pubkey(lua_State *L) {
1161 initall(L);
1162
1163 luaL_newlib(L, pk_globals);
1164
1165 return 1;
1166} /* luaopen__openssl_pubkey() */
1167
1168
1169/*
1170 * X509_NAME - openssl.x509.name
1171 *
1172 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1173
1174static X509_NAME *xn_dup(lua_State *L, X509_NAME *name) {
1175 X509_NAME **ud = prepsimple(L, X509_NAME_CLASS);
1176
1177 if (!(*ud = X509_NAME_dup(name)))
1178 throwssl(L, "x509.name.dup");
1179
1180 return *ud;
1181} /* xn_dup() */
1182
1183
1184static int xn_new(lua_State *L) {
1185 X509_NAME **ud = prepsimple(L, X509_NAME_CLASS);
1186
1187 if (!(*ud = X509_NAME_new()))
1188 return throwssl(L, "x509.name.new");
1189
1190 return 1;
1191} /* xn_new() */
1192
1193
1194static int xn_interpose(lua_State *L) {
1195 return interpose(L, X509_NAME_CLASS);
1196} /* xn_interpose() */
1197
1198
1199static int xn_add(lua_State *L) {
1200 X509_NAME *name = checksimple(L, 1, X509_NAME_CLASS);
1201 const char *nid = luaL_checkstring(L, 2);
1202 size_t len;
1203 const char *txt = luaL_checklstring(L, 3, &len);
1204 ASN1_OBJECT *obj;
1205 int ok;
1206
1207 if (!(obj = OBJ_txt2obj(nid, 0)))
1208 return luaL_error(L, "x509.name:add: %s: invalid NID", nid);
1209
1210 ok = !!X509_NAME_add_entry_by_OBJ(name, obj, MBSTRING_ASC, (unsigned char *)txt, len, -1, 0);
1211
1212 ASN1_OBJECT_free(obj);
1213
1214 if (!ok)
1215 return throwssl(L, "x509.name:add");
1216
1217 lua_pushboolean(L, 1);
1218
1219 return 1;
1220} /* xn_add() */
1221
1222
1223static int xn_all(lua_State *L) {
1224 X509_NAME *name = checksimple(L, 1, X509_NAME_CLASS);
1225 int count = X509_NAME_entry_count(name);
1226 X509_NAME_ENTRY *entry;
1227 ASN1_OBJECT *obj;
1228 const char *id;
1229 char txt[256];
1230 int i, nid, len;
1231
1232 lua_newtable(L);
1233
1234 for (i = 0; i < count; i++) {
1235 if (!(entry = X509_NAME_get_entry(name, i)))
1236 continue;
1237
1238 lua_newtable(L);
1239
1240 obj = X509_NAME_ENTRY_get_object(entry);
1241 nid = OBJ_obj2nid(obj);
1242
1243 if (0 > (len = OBJ_obj2txt(txt, sizeof txt, obj, 1)))
1244 return throwssl(L, "x509.name:all");
1245
1246 lua_pushlstring(L, txt, len);
1247
1248 if (nid != NID_undef && ((id = OBJ_nid2ln(nid)) || (id = OBJ_nid2sn(nid))))
1249 lua_pushstring(L, id);
1250 else
1251 lua_pushvalue(L, -1);
1252
1253 if (nid != NID_undef && (id = OBJ_nid2sn(nid)))
1254 lua_pushstring(L, id);
1255 else
1256 lua_pushvalue(L, -1);
1257
1258 lua_setfield(L, -4, "sn");
1259 lua_setfield(L, -3, "ln");
1260 lua_setfield(L, -2, "id");
1261
1262 len = ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry));
1263 lua_pushlstring(L, (char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), len);
1264
1265 lua_setfield(L, -2, "blob");
1266
1267 lua_rawseti(L, -2, i + 1);
1268 }
1269
1270 return 1;
1271} /* xn_all() */
1272
1273
1274static int xn__next(lua_State *L) {
1275 X509_NAME *name = checksimple(L, lua_upvalueindex(1), X509_NAME_CLASS);
1276 X509_NAME_ENTRY *entry;
1277 ASN1_OBJECT *obj;
1278 const char *id;
1279 char txt[256];
1280 int i, n, nid, len;
1281
1282 lua_settop(L, 0);
1283
1284 i = lua_tointeger(L, lua_upvalueindex(2));
1285 n = X509_NAME_entry_count(name);
1286
1287 while (i < n) {
1288 if (!(entry = X509_NAME_get_entry(name, i++)))
1289 continue;
1290
1291 obj = X509_NAME_ENTRY_get_object(entry);
1292 nid = OBJ_obj2nid(obj);
1293
1294 if (nid != NID_undef && ((id = OBJ_nid2sn(nid)) || (id = OBJ_nid2ln(nid)))) {
1295 lua_pushstring(L, id);
1296 } else {
1297 if (0 > (len = OBJ_obj2txt(txt, sizeof txt, obj, 1)))
1298 return throwssl(L, "x509.name:__pairs");
1299
1300 lua_pushlstring(L, txt, len);
1301 }
1302
1303 len = ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry));
1304 lua_pushlstring(L, (char *)ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), len);
1305
1306 break;
1307 }
1308
1309 lua_pushinteger(L, i);
1310 lua_replace(L, lua_upvalueindex(2));
1311
1312 return lua_gettop(L);
1313} /* xn__next() */
1314
1315static int xn__pairs(lua_State *L) {
1316 lua_settop(L, 1);
1317 lua_pushinteger(L, 0);
1318
1319 lua_pushcclosure(L, &xn__next, 2);
1320
1321 return 1;
1322} /* xn__pairs() */
1323
1324
1325static int xn__gc(lua_State *L) {
1326 X509_NAME **ud = luaL_checkudata(L, 1, X509_NAME_CLASS);
1327
1328 X509_NAME_free(*ud);
1329 *ud = NULL;
1330
1331 return 0;
1332} /* xn__gc() */
1333
1334
1335static int xn__tostring(lua_State *L) {
1336 X509_NAME *name = checksimple(L, 1, X509_NAME_CLASS);
1337 char txt[1024] = { 0 };
1338
1339 /* FIXME: oneline is deprecated */
1340 X509_NAME_oneline(name, txt, sizeof txt);
1341
1342 lua_pushstring(L, txt);
1343
1344 return 1;
1345} /* xn__tostring() */
1346
1347
1348static const luaL_Reg xn_methods[] = {
1349 { "add", &xn_add },
1350 { "all", &xn_all },
1351 { NULL, NULL },
1352};
1353
1354static const luaL_Reg xn_metatable[] = {
1355 { "__pairs", &xn__pairs },
1356 { "__gc", &xn__gc },
1357 { "__tostring", &xn__tostring },
1358 { NULL, NULL },
1359};
1360
1361
1362static const luaL_Reg xn_globals[] = {
1363 { "new", &xn_new },
1364 { "interpose", &xn_interpose },
1365 { NULL, NULL },
1366};
1367
1368int luaopen__openssl_x509_name(lua_State *L) {
1369 initall(L);
1370
1371 luaL_newlib(L, xn_globals);
1372
1373 return 1;
1374} /* luaopen__openssl_x509_name() */
1375
1376
1377/*
1378 * GENERAL_NAMES - openssl.x509.altname
1379 *
1380 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1381
1382static GENERAL_NAMES *gn_dup(lua_State *L, GENERAL_NAMES *gens) {
1383 GENERAL_NAMES **ud = prepsimple(L, X509_GENS_CLASS);
1384
1385 if (!(*ud = sk_GENERAL_NAME_dup(gens)))
1386 throwssl(L, "x509.altname.dup");
1387
1388 return *ud;
1389} /* gn_dup() */
1390
1391
1392static int gn_new(lua_State *L) {
1393 GENERAL_NAMES **ud = prepsimple(L, X509_GENS_CLASS);
1394
1395 if (!(*ud = sk_GENERAL_NAME_new_null()))
1396 return throwssl(L, "x509.altname.new");
1397
1398 return 1;
1399} /* gn_new() */
1400
1401
1402static int gn_interpose(lua_State *L) {
1403 return interpose(L, X509_GENS_CLASS);
1404} /* gn_interpose() */
1405
1406
1407static int gn_setCritical(lua_State *L) {
1408 GENERAL_NAMES *gens = checksimple(L, 1, X509_GENS_CLASS);
1409
1410 return 0;
1411} /* gn_setCritical() */
1412
1413
1414static int gn_checktype(lua_State *L, int index) {
1415 static const struct { int type; const char *name; } table[] = {
1416 { GEN_EMAIL, "RFC822Name" },
1417 { GEN_EMAIL, "RFC822" },
1418 { GEN_EMAIL, "email" },
1419 { GEN_URI, "UniformResourceIdentifier" },
1420 { GEN_URI, "URI" },
1421 { GEN_DNS, "DNSName" },
1422 { GEN_DNS, "DNS" },
1423 { GEN_IPADD, "IPAddress" },
1424 { GEN_IPADD, "IP" },
1425 };
1426 const char *type = luaL_checkstring(L, index);
1427 unsigned i;
1428
1429 for (i = 0; i < countof(table); i++) {
1430 if (strieq(table[i].name, type))
1431 return table[i].type;
1432 }
1433
1434 return luaL_error(L, "%s: invalid type", type), 0;
1435} /* gn_checktype() */
1436
1437
1438static int gn_add(lua_State *L) {
1439 GENERAL_NAMES *gens = checksimple(L, 1, X509_GENS_CLASS);
1440 int type = gn_checktype(L, 2);
1441 size_t len;
1442 const char *txt = luaL_checklstring(L, 3, &len);
1443 GENERAL_NAME *gen = NULL;
1444 union { struct in6_addr in6; struct in_addr in; } ip;
1445
1446 if (type == GEN_IPADD) {
1447 if (strchr(txt, ':')) {
1448 if (1 != inet_pton(AF_INET6, txt, &ip.in6))
1449 return luaL_error(L, "%s: invalid address", txt);
1450
1451 txt = (char *)ip.in6.s6_addr;
1452 len = 16;
1453 } else {
1454 if (1 != inet_pton(AF_INET, txt, &ip.in))
1455 return luaL_error(L, "%s: invalid address", txt);
1456
1457 txt = (char *)&ip.in.s_addr;
1458 len = 4;
1459 }
1460 }
1461
1462 if (!(gen = GENERAL_NAME_new()))
1463 goto error;
1464
1465 gen->type = type;
1466
1467 if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()))
1468 goto error;
1469
1470 if (!ASN1_STRING_set(gen->d.ia5, (unsigned char *)txt, len))
1471 goto error;
1472
1473 sk_GENERAL_NAME_push(gens, gen);
1474
1475 lua_pushboolean(L, 1);
1476
1477 return 1;
1478error:
1479 GENERAL_NAME_free(gen);
1480
1481 return throwssl(L, "x509.altname:add");
1482} /* gn_add() */
1483
1484
1485static int gn__next(lua_State *L) {
1486 GENERAL_NAMES *gens = checksimple(L, lua_upvalueindex(1), X509_GENS_CLASS);
1487 int i = lua_tointeger(L, lua_upvalueindex(2));
1488 int n = sk_GENERAL_NAME_num(gens);
1489
1490 lua_settop(L, 0);
1491
1492 while (i < n) {
1493 GENERAL_NAME *name;
1494 const char *tag, *txt;
1495 size_t len;
1496 union { struct in_addr in; struct in6_addr in6; } ip;
1497 char buf[INET6_ADDRSTRLEN + 1];
1498 int af;
1499
1500 if (!(name = sk_GENERAL_NAME_value(gens, i++)))
1501 continue;
1502
1503 switch (name->type) {
1504 case GEN_EMAIL:
1505 tag = "email";
1506 txt = (char *)M_ASN1_STRING_data(name->d.rfc822Name);
1507 len = M_ASN1_STRING_length(name->d.rfc822Name);
1508
1509 break;
1510 case GEN_URI:
1511 tag = "URI";
1512 txt = (char *)M_ASN1_STRING_data(name->d.uniformResourceIdentifier);
1513 len = M_ASN1_STRING_length(name->d.uniformResourceIdentifier);
1514
1515 break;
1516 case GEN_DNS:
1517 tag = "DNS";
1518 txt = (char *)M_ASN1_STRING_data(name->d.dNSName);
1519 len = M_ASN1_STRING_length(name->d.dNSName);
1520
1521 break;
1522 case GEN_IPADD:
1523 tag = "IP";
1524 txt = (char *)M_ASN1_STRING_data(name->d.iPAddress);
1525 len = M_ASN1_STRING_length(name->d.iPAddress);
1526
1527 switch (len) {
1528 case 16:
1529 memcpy(ip.in6.s6_addr, txt, 16);
1530 af = AF_INET6;
1531
1532 break;
1533 case 4:
1534 memcpy(&ip.in.s_addr, txt, 4);
1535 af = AF_INET;
1536
1537 break;
1538 default:
1539 continue;
1540 }
1541
1542 if (!(txt = inet_ntop(af, &ip, buf, sizeof buf)))
1543 continue;
1544
1545 len = strlen(txt);
1546
1547 break;
1548 default:
1549 continue;
1550 }
1551
1552 lua_pushstring(L, tag);
1553 lua_pushlstring(L, txt, len);
1554
1555 break;
1556 }
1557
1558 lua_pushinteger(L, i);
1559 lua_replace(L, lua_upvalueindex(2));
1560
1561 return lua_gettop(L);
1562} /* gn__next() */
1563
1564static int gn__pairs(lua_State *L) {
1565 lua_settop(L, 1);
1566 lua_pushinteger(L, 0);
1567 lua_pushcclosure(L, &gn__next, 2);
1568
1569 return 1;
1570} /* gn__pairs() */
1571
1572
1573static int gn__gc(lua_State *L) {
1574 GENERAL_NAMES **ud = luaL_checkudata(L, 1, X509_GENS_CLASS);
1575
1576 sk_GENERAL_NAME_pop_free(*ud, GENERAL_NAME_free);
1577 *ud = NULL;
1578
1579 return 0;
1580} /* gn__gc() */
1581
1582
1583static const luaL_Reg gn_methods[] = {
1584 { "add", &gn_add },
1585 { NULL, NULL },
1586};
1587
1588static const luaL_Reg gn_metatable[] = {
1589 { "__pairs", &gn__pairs },
1590 { "__gc", &gn__gc },
1591 { NULL, NULL },
1592};
1593
1594
1595static const luaL_Reg gn_globals[] = {
1596 { "new", &gn_new },
1597 { "interpose", &gn_interpose },
1598 { NULL, NULL },
1599};
1600
1601int luaopen__openssl_x509_altname(lua_State *L) {
1602 initall(L);
1603
1604 luaL_newlib(L, gn_globals);
1605
1606 return 1;
1607} /* luaopen__openssl_x509_altname() */
1608
1609
1610/*
1611 * X509 - openssl.x509.cert
1612 *
1613 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1614
1615static int xc_new(lua_State *L) {
1616 const char *pem;
1617 size_t len;
1618 X509 **ud;
1619
1620 lua_settop(L, 1);
1621
1622 ud = prepsimple(L, X509_CERT_CLASS);
1623
1624 if ((pem = luaL_optlstring(L, 1, NULL, &len))) {
1625 BIO *tmp;
1626 int ok;
1627
1628 if (!(tmp = BIO_new_mem_buf((char *)pem, len)))
1629 return throwssl(L, "x509.cert.new");
1630
1631 ok = !!PEM_read_bio_X509(tmp, ud, 0, ""); /* no password */
1632
1633 BIO_free(tmp);
1634
1635 if (!ok)
1636 return throwssl(L, "x509.cert.new");
1637 } else {
1638 if (!(*ud = X509_new()))
1639 return throwssl(L, "x509.cert.new");
1640
1641 X509_gmtime_adj(X509_get_notBefore(*ud), 0);
1642 X509_gmtime_adj(X509_get_notAfter(*ud), 0);
1643 }
1644
1645 return 1;
1646} /* xc_new() */
1647
1648
1649static int xc_interpose(lua_State *L) {
1650 return interpose(L, X509_CERT_CLASS);
1651} /* xc_interpose() */
1652
1653
1654static int xc_getVersion(lua_State *L) {
1655 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1656
1657 lua_pushinteger(L, X509_get_version(crt) + 1);
1658
1659 return 1;
1660} /* xc_getVersion() */
1661
1662
1663static int xc_setVersion(lua_State *L) {
1664 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1665 int version = luaL_checkint(L, 2);
1666
1667 if (!X509_set_version(crt, version - 1))
1668 return luaL_error(L, "x509.cert:setVersion: %d: invalid version", version);
1669
1670 lua_pushboolean(L, 1);
1671
1672 return 1;
1673} /* xc_setVersion() */
1674
1675
1676static int xc_getSerial(lua_State *L) {
1677 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1678 BIGNUM *serial = bn_push(L);
1679 ASN1_INTEGER *i;
1680
1681 if ((i = X509_get_serialNumber(crt))) {
1682 if (!ASN1_INTEGER_to_BN(i, serial))
1683 return throwssl(L, "x509.cert:getSerial");
1684 }
1685
1686 return 1;
1687} /* xc_getSerial() */
1688
1689
1690static int xc_setSerial(lua_State *L) {
1691 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1692 ASN1_INTEGER *serial;
1693
1694 if (!(serial = BN_to_ASN1_INTEGER(checkbig(L, 2), NULL)))
1695 goto error;
1696
1697 if (!X509_set_serialNumber(crt, serial))
1698 goto error;
1699
1700 ASN1_INTEGER_free(serial);
1701
1702 lua_pushboolean(L, 1);
1703
1704 return 1;
1705error:
1706 ASN1_INTEGER_free(serial);
1707
1708 return throwssl(L, "x509.cert:setSerial");
1709} /* xc_setSerial() */
1710
1711
1712static int xc_digest(lua_State *L) {
1713 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1714 const char *type = luaL_optstring(L, 2, "sha1");
1715 int format = luaL_checkoption(L, 3, "x", (const char *[]){ "s", "x", "n", NULL });
1716 const EVP_MD *ctx;
1717 unsigned char md[EVP_MAX_MD_SIZE];
1718 unsigned len;
1719
1720 lua_settop(L, 3); /* self, type, hex */
1721
1722 if (!(ctx = EVP_get_digestbyname(type)))
1723 return luaL_error(L, "x509.cert:digest: %s: invalid digest type", type);
1724
1725 X509_digest(crt, ctx, md, &len);
1726
1727 switch (format) {
1728 case 2: {
1729 BIGNUM *bn = bn_push(L);
1730
1731 if (!BN_bin2bn(md, len, bn))
1732 return throwssl(L, "x509.cert:digest");
1733
1734 break;
1735 }
1736 case 1: {
1737 static const unsigned char x[16] = "0123456789abcdef";
1738 luaL_Buffer B;
1739 unsigned i;
1740
1741#if LUA_VERSION_NUM < 502
1742 luaL_buffinit(L, &B);
1743#else
1744 luaL_buffinitsize(L, &B, 2 * len);
1745#endif
1746
1747 for (i = 0; i < len; i++) {
1748 luaL_addchar(&B, x[0x0f & (md[i] >> 4)]);
1749 luaL_addchar(&B, x[0x0f & (md[i] >> 0)]);
1750 }
1751
1752 luaL_pushresult(&B);
1753
1754 break;
1755 }
1756 default:
1757 lua_pushlstring(L, (const char *)md, len);
1758
1759 break;
1760 } /* switch() */
1761
1762 return 1;
1763} /* xc_digest() */
1764
1765
1766static _Bool isleap(int year) {
1767 if (year >= 0)
1768 return !(year % 4) && ((year % 100) || !(year % 400));
1769 else
1770 return isleap(-(year + 1));
1771} /* isleap() */
1772
1773
1774static int yday(int year, int mon, int mday) {
1775 static const int past[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1776 int yday = past[CLAMP(mon, 0, 11)] + CLAMP(mday, 1, 31) - 1;
1777
1778 return yday + (mon > 1 && isleap(year));
1779} /* yday() */
1780
1781
1782static int tm_yday(const struct tm *tm) {
1783 return (tm->tm_yday)? tm->tm_yday : yday(1900 + tm->tm_year, tm->tm_mon, tm->tm_mday);
1784} /* tm_yday() */
1785
1786
1787static int leaps(int year) {
1788 if (year >= 0)
1789 return (year / 400) + (year / 4) - (year / 100);
1790 else
1791 return -(leaps(-(year + 1)) + 1);
1792} /* leaps() */
1793
1794
1795static double tm2unix(const struct tm *tm, int gmtoff) {
1796 int year = tm->tm_year + 1900;
1797 double ts;
1798
1799 ts = 86400.0 * 365.0 * (year - 1970);
1800 ts += 86400.0 * (leaps(year - 1) - leaps(1969));
1801 ts += 86400 * tm_yday(tm);
1802 ts += 3600 * tm->tm_hour;
1803 ts += 60 * tm->tm_min;
1804 ts += CLAMP(tm->tm_sec, 0, 59);
1805 ts += (year < 1970)? gmtoff : -gmtoff;
1806
1807 return ts;
1808} /* tm2unix() */
1809
1810
1811static _Bool scan(int *i, char **cp, int n, int signok) {
1812 int sign = 1;
1813
1814 *i = 0;
1815
1816 if (signok) {
1817 if (**cp == '-') {
1818 sign = -1;
1819 ++*cp;
1820 } else if (**cp == '+') {
1821 ++*cp;
1822 }
1823 }
1824
1825 while (n-- > 0) {
1826 if (**cp < '0' || **cp > '9')
1827 return 0;
1828
1829 *i *= 10;
1830 *i += *(*cp)++ - '0';
1831 }
1832
1833 *i *= sign;
1834
1835 return 1;
1836} /* scan() */
1837
1838
1839static double timeutc(ASN1_TIME *time) {
1840 char buf[32] = "", *cp;
1841 struct tm tm = { 0 };
1842 int gmtoff = 0, year, i;
1843 double ts;
1844
1845 if (!ASN1_TIME_check(time))
1846 return 0;
1847
1848 cp = strncpy(buf, (const char *)ASN1_STRING_data((ASN1_STRING *)time), sizeof buf - 1);
1849
1850 if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) {
1851 if (!scan(&year, &cp, 4, 1))
1852 goto badfmt;
1853 } else {
1854 if (!scan(&year, &cp, 2, 0))
1855 goto badfmt;
1856 year += (year < 50)? 2000 : 1999;
1857 }
1858
1859 tm.tm_year = year - 1900;
1860
1861 if (!scan(&i, &cp, 2, 0))
1862 goto badfmt;
1863
1864 tm.tm_mon = CLAMP(i, 1, 12) - 1;
1865
1866 if (!scan(&i, &cp, 2, 0))
1867 goto badfmt;
1868
1869 tm.tm_mday = CLAMP(i, 1, 31);
1870
1871 tm.tm_yday = yday(year, tm.tm_mon, tm.tm_mday);
1872
1873 if (!scan(&i, &cp, 2, 0))
1874 goto badfmt;
1875
1876 tm.tm_hour = CLAMP(i, 0, 23);
1877
1878 if (!scan(&i, &cp, 2, 0))
1879 goto badfmt;
1880
1881 tm.tm_min = CLAMP(i, 0, 59);
1882
1883 if (*cp >= '0' && *cp <= '9') {
1884 if (!scan(&i, &cp, 2, 0))
1885 goto badfmt;
1886
1887 tm.tm_sec = CLAMP(i, 0, 59);
1888 }
1889
1890 if (*cp == '+' || *cp == '-') {
1891 int sign = (*cp++ == '-')? -1 : 1;
1892 int hh, mm;
1893
1894 if (!scan(&hh, &cp, 2, 0) || !scan(&mm, &cp, 2, 0))
1895 goto badfmt;
1896
1897 gmtoff = (CLAMP(hh, 0, 23) * 3600)
1898 + (CLAMP(mm, 0, 59) * 60);
1899
1900 gmtoff *= sign;
1901 }
1902
1903 return tm2unix(&tm, gmtoff);
1904badfmt:
1905 return INFINITY;
1906} /* timeutc() */
1907
1908
1909static int xc_getLifetime(lua_State *L) {
1910 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1911 double begin = INFINITY, end = INFINITY;
1912 ASN1_TIME *time;
1913
1914 if ((time = X509_get_notBefore(crt)))
1915 begin = timeutc(time);
1916
1917 if ((time = X509_get_notAfter(crt)))
1918 end = timeutc(time);
1919
1920 if (isfinite(begin))
1921 lua_pushnumber(L, begin);
1922 else
1923 lua_pushnil(L);
1924
1925 if (isfinite(end))
1926 lua_pushnumber(L, end);
1927 else
1928 lua_pushnil(L);
1929
1930 if (isfinite(begin) && isfinite(end) && begin <= end)
1931 lua_pushnumber(L, fabs(end - begin));
1932 else
1933 lua_pushnumber(L, 0.0);
1934
1935 return 3;
1936} /* xc_getLifetime() */
1937
1938
1939static int xc_setLifetime(lua_State *L) {
1940 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1941 ASN1_TIME *time;
1942 double ut;
1943 const char *dt;
1944
1945 lua_settop(L, 3);
1946
1947 if (lua_isnumber(L, 2)) {
1948 ut = lua_tonumber(L, 2);
1949
1950 if (!ASN1_TIME_set(X509_get_notBefore(crt), ut))
1951 return throwssl(L, "x509.cert:setLifetime");
1952#if 0
1953 } else if ((dt = luaL_optstring(L, 2, 0))) {
1954 if (!ASN1_TIME_set_string(X509_get_notBefore(crt), dt))
1955 return throwssl(L, "x509.cert:setLifetime");
1956#endif
1957 }
1958
1959 if (lua_isnumber(L, 3)) {
1960 ut = lua_tonumber(L, 3);
1961
1962 if (!ASN1_TIME_set(X509_get_notAfter(crt), ut))
1963 return throwssl(L, "x509.cert:setLifetime");
1964#if 0
1965 } else if ((dt = luaL_optstring(L, 3, 0))) {
1966 if (!ASN1_TIME_set_string(X509_get_notAfter(crt), dt))
1967 return throwssl(L, "x509.cert:setLifetime");
1968#endif
1969 }
1970
1971 lua_pushboolean(L, 1);
1972
1973 return 1;
1974} /* xc_setLifetime() */
1975
1976
1977static int xc_getIssuer(lua_State *L) {
1978 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1979 X509_NAME *name;
1980
1981 if (!(name = X509_get_issuer_name(crt)))
1982 return 0;
1983
1984 xn_dup(L, name);
1985
1986 return 1;
1987} /* xc_getIssuer() */
1988
1989
1990static int xc_setIssuer(lua_State *L) {
1991 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
1992 X509_NAME *name = checksimple(L, 2, X509_NAME_CLASS);
1993
1994 if (!X509_set_issuer_name(crt, name))
1995 return throwssl(L, "x509.cert:setIssuer");
1996
1997 lua_pushboolean(L, 1);
1998
1999 return 1;
2000} /* xc_setIssuer() */
2001
2002
2003static int xc_getSubject(lua_State *L) {
2004 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2005 X509_NAME *name;
2006
2007 if (!(name = X509_get_subject_name(crt)))
2008 return 0;
2009
2010 xn_dup(L, name);
2011
2012 return 1;
2013} /* xc_getSubject() */
2014
2015
2016static int xc_setSubject(lua_State *L) {
2017 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2018 X509_NAME *name = checksimple(L, 2, X509_NAME_CLASS);
2019
2020 if (!X509_set_subject_name(crt, name))
2021 return throwssl(L, "x509.cert:setSubject");
2022
2023 lua_pushboolean(L, 1);
2024
2025 return 1;
2026} /* xc_setSubject() */
2027
2028
2029static void xc_setCritical(X509 *crt, int nid, _Bool yes) {
2030 X509_EXTENSION *ext;
2031 int loc;
2032
2033 if ((loc = X509_get_ext_by_NID(crt, nid, -1)) >= 0
2034 && (ext = X509_get_ext(crt, loc)))
2035 X509_EXTENSION_set_critical(ext, yes);
2036} /* xc_setCritical() */
2037
2038
2039static _Bool xc_getCritical(X509 *crt, int nid) {
2040 X509_EXTENSION *ext;
2041 int loc;
2042
2043 if ((loc = X509_get_ext_by_NID(crt, nid, -1)) >= 0
2044 && (ext = X509_get_ext(crt, loc)))
2045 return X509_EXTENSION_get_critical(ext);
2046 else
2047 return 0;
2048} /* xc_getCritical() */
2049
2050
2051static int xc_getIssuerAlt(lua_State *L) {
2052 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2053 GENERAL_NAMES *gens;
2054
2055 if (!(gens = X509_get_ext_d2i(crt, NID_issuer_alt_name, 0, 0)))
2056 return 0;
2057
2058 gn_dup(L, gens);
2059
2060 return 1;
2061} /* xc_getIssuerAlt() */
2062
2063
2064static int xc_setIssuerAlt(lua_State *L) {
2065 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2066 GENERAL_NAMES *gens = checksimple(L, 2, X509_GENS_CLASS);
2067
2068 if (!X509_add1_ext_i2d(crt, NID_issuer_alt_name, gens, 0, X509V3_ADD_REPLACE))
2069 return throwssl(L, "x509.altname:setIssuerAlt");
2070
2071 lua_pushboolean(L, 1);
2072
2073 return 1;
2074} /* xc_setIssuerAlt() */
2075
2076
2077static int xc_getSubjectAlt(lua_State *L) {
2078 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2079 GENERAL_NAMES *gens;
2080
2081 if (!(gens = X509_get_ext_d2i(crt, NID_subject_alt_name, 0, 0)))
2082 return 0;
2083
2084 gn_dup(L, gens);
2085
2086 return 1;
2087} /* xc_getSubjectAlt() */
2088
2089
2090static int xc_setSubjectAlt(lua_State *L) {
2091 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2092 GENERAL_NAMES *gens = checksimple(L, 2, X509_GENS_CLASS);
2093
2094 if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, X509V3_ADD_REPLACE))
2095 return throwssl(L, "x509.altname:setSubjectAlt");
2096
2097 lua_pushboolean(L, 1);
2098
2099 return 1;
2100} /* xc_setSubjectAlt() */
2101
2102
2103static int xc_getIssuerAltCritical(lua_State *L) {
2104 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2105
2106 lua_pushboolean(L, xc_getCritical(crt, NID_issuer_alt_name));
2107
2108 return 1;
2109} /* xc_getIssuerAltCritical() */
2110
2111
2112static int xc_setIssuerAltCritical(lua_State *L) {
2113 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2114
2115 luaL_checkany(L, 2);
2116 xc_setCritical(crt, NID_issuer_alt_name, lua_toboolean(L, 2));
2117
2118 lua_pushboolean(L, 1);
2119
2120 return 1;
2121} /* xc_setIssuerAltCritical() */
2122
2123
2124static int xc_getSubjectAltCritical(lua_State *L) {
2125 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2126
2127 lua_pushboolean(L, xc_getCritical(crt, NID_subject_alt_name));
2128
2129 return 1;
2130} /* xc_getSubjectAltCritical() */
2131
2132
2133static int xc_setSubjectAltCritical(lua_State *L) {
2134 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2135
2136 luaL_checkany(L, 2);
2137 xc_setCritical(crt, NID_subject_alt_name, lua_toboolean(L, 2));
2138
2139 lua_pushboolean(L, 1);
2140
2141 return 1;
2142} /* xc_setSubjectAltCritical() */
2143
2144
2145static int xc_getBasicConstraint(lua_State *L) {
2146 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2147 BASIC_CONSTRAINTS *bs;
2148 int CA, pathLen;
2149
2150 if (!(bs = X509_get_ext_d2i(crt, NID_basic_constraints, 0, 0))) {
2151 /* FIXME: detect error or just non-existent */
2152
2153 if (lua_gettop(L) > 1)
2154 return 0;
2155
2156 lua_newtable(L);
2157
2158 return 1;
2159 }
2160
2161 CA = bs->ca;
2162 pathLen = ASN1_INTEGER_get(bs->pathlen);
2163
2164 BASIC_CONSTRAINTS_free(bs);
2165
2166 if (lua_gettop(L) > 1) {
2167 int n = 0, i, top;
2168
2169 for (i = 2, top = lua_gettop(L); i <= top; i++) {
2170 switch (checkoption(L, i, 0, (const char *[]){ "CA", "pathLen", "pathLenConstraint", NULL })) {
2171 case 0:
2172 lua_pushboolean(L, CA);
2173 n++;
2174 break;
2175 case 1:
2176 /* FALL THROUGH */
2177 case 2:
2178 lua_pushinteger(L, pathLen);
2179 n++;
2180 break;
2181 }
2182 }
2183
2184 return n;
2185 } else {
2186 lua_newtable(L);
2187
2188 lua_pushboolean(L, CA);
2189 lua_setfield(L, -2, "CA");
2190
2191 lua_pushinteger(L, pathLen);
2192 lua_setfield(L, -2, "pathLen");
2193
2194 return 1;
2195 }
2196} /* xc_getBasicConstraint() */
2197
2198
2199static int xc_setBasicConstraint(lua_State *L) {
2200 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2201 BASIC_CONSTRAINTS *bs = 0;
2202 int CA = -1, pathLen = -1;
2203 int critical = 0;
2204
2205 luaL_checkany(L, 2);
2206
2207 if (lua_istable(L, 2)) {
2208 lua_getfield(L, 2, "CA");
2209 if (!lua_isnil(L, -1))
2210 CA = lua_toboolean(L, -1);
2211 lua_pop(L, 1);
2212
2213 lua_getfield(L, 2, "pathLen");
2214 pathLen = luaL_optint(L, -1, pathLen);
2215 lua_pop(L, 1);
2216
2217 lua_getfield(L, 2, "pathLenConstraint");
2218 pathLen = luaL_optint(L, -1, pathLen);
2219 lua_pop(L, 1);
2220
2221 if (!(bs = BASIC_CONSTRAINTS_new()))
2222 goto error;
2223 } else {
2224 lua_settop(L, 3);
2225
2226 switch (checkoption(L, 2, 0, (const char *[]){ "CA", "pathLen", "pathLenConstraint", NULL })) {
2227 case 0:
2228 luaL_checktype(L, 3, LUA_TBOOLEAN);
2229 CA = lua_toboolean(L, 3);
2230
2231 break;
2232 case 1:
2233 /* FALL THROUGH */
2234 case 2:
2235 pathLen = luaL_checkint(L, 3);
2236
2237 break;
2238 }
2239
2240 if (!(bs = X509_get_ext_d2i(crt, NID_basic_constraints, &critical, 0))) {
2241 /* FIXME: detect whether error or just non-existent */
2242 if (!(bs = BASIC_CONSTRAINTS_new()))
2243 goto error;
2244 }
2245 }
2246
2247 if (CA != -1)
2248 bs->ca = CA;
2249
2250 if (pathLen >= 0) {
2251 ASN1_INTEGER_free(bs->pathlen);
2252
2253 if (!(bs->pathlen = M_ASN1_INTEGER_new()))
2254 goto error;
2255
2256 if (!ASN1_INTEGER_set(bs->pathlen, pathLen))
2257 goto error;
2258 }
2259
2260 if (!X509_add1_ext_i2d(crt, NID_basic_constraints, bs, critical, X509V3_ADD_REPLACE))
2261 goto error;
2262
2263 BASIC_CONSTRAINTS_free(bs);
2264
2265 lua_pushboolean(L, 1);
2266
2267 return 1;
2268error:
2269 BASIC_CONSTRAINTS_free(bs);
2270
2271 return throwssl(L, "x509.cert:setBasicConstraint");
2272} /* xc_setBasicConstraint() */
2273
2274
2275static int xc_getBasicConstraintsCritical(lua_State *L) {
2276 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2277
2278 lua_pushboolean(L, xc_getCritical(crt, NID_basic_constraints));
2279
2280 return 1;
2281} /* xc_getBasicConstraintsCritical() */
2282
2283
2284static int xc_setBasicConstraintsCritical(lua_State *L) {
2285 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2286
2287 luaL_checkany(L, 2);
2288 xc_setCritical(crt, NID_basic_constraints, lua_toboolean(L, 2));
2289
2290 lua_pushboolean(L, 1);
2291
2292 return 1;
2293} /* xc_setBasicConstraintsCritical() */
2294
2295
2296static int xc_isIssuedBy(lua_State *L) {
2297 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2298 X509 *issuer = checksimple(L, 2, X509_CERT_CLASS);
2299 EVP_PKEY *key;
2300 int ok, why = 0;
2301
2302 ERR_clear_error();
2303
2304 if (X509_V_OK != (why = X509_check_issued(issuer, crt)))
2305 goto done;
2306
2307 if (!(key = X509_get_pubkey(issuer))) {
2308 why = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
2309 goto done;
2310 }
2311
2312 ok = (1 == X509_verify(crt, key));
2313
2314 EVP_PKEY_free(key);
2315
2316 if (!ok)
2317 why = X509_V_ERR_CERT_SIGNATURE_FAILURE;
2318
2319done:
2320 if (why != X509_V_OK) {
2321 lua_pushboolean(L, 0);
2322 lua_pushstring(L, X509_verify_cert_error_string(why));
2323
2324 return 2;
2325 } else {
2326 lua_pushboolean(L, 1);
2327
2328 return 1;
2329 }
2330} /* xc_isIssuedBy() */
2331
2332
2333static int xc_getPublicKey(lua_State *L) {
2334 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2335 EVP_PKEY **key = prepsimple(L, PUBKEY_CLASS);
2336
2337 if (!(*key = X509_get_pubkey(crt)))
2338 return throwssl(L, "x509.cert:getPublicKey");
2339
2340 return 1;
2341} /* xc_getPublicKey() */
2342
2343
2344static int xc_setPublicKey(lua_State *L) {
2345 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2346 EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
2347
2348 if (!X509_set_pubkey(crt, key))
2349 return throwssl(L, "x509.cert:setPublicKey");
2350
2351 lua_pushboolean(L, 1);
2352
2353 return 1;
2354} /* xc_setPublicKey() */
2355
2356
2357static const EVP_MD *xc_signature(lua_State *L, int index, EVP_PKEY *key) {
2358 const char *id;
2359 const EVP_MD *md;
2360
2361 if ((id = luaL_optstring(L, index, NULL)))
2362 return ((md = EVP_get_digestbyname(id)))? md : EVP_md_null();
2363
2364 switch (EVP_PKEY_type(key->type)) {
2365 case EVP_PKEY_RSA:
2366 return EVP_sha1();
2367 case EVP_PKEY_DSA:
2368 return EVP_dss1();
2369 case EVP_PKEY_EC:
2370 return EVP_ecdsa();
2371 default:
2372 return EVP_md_null();
2373 }
2374} /* xc_signature() */
2375
2376static int xc_sign(lua_State *L) {
2377 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2378 EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
2379
2380 if (!X509_sign(crt, key, xc_signature(L, 3, key)))
2381 return throwssl(L, "x509.cert:sign");
2382
2383 lua_pushboolean(L, 1);
2384
2385 return 1;
2386} /* xc_sign() */
2387
2388
2389static int xc__tostring(lua_State *L) {
2390 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
2391 int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", NULL });
2392 BIO *bio = getbio(L);
2393 char *pem;
2394 long len;
2395
2396 if (!PEM_write_bio_X509(bio, crt))
2397 return throwssl(L, "x509.cert:__tostring");
2398
2399 len = BIO_get_mem_data(bio, &pem);
2400
2401 lua_pushlstring(L, pem, len);
2402
2403 return 1;
2404} /* xc__tostring() */
2405
2406
2407static int xc__gc(lua_State *L) {
2408 X509 **ud = luaL_checkudata(L, 1, X509_CERT_CLASS);
2409
2410 X509_free(*ud);
2411 *ud = NULL;
2412
2413 return 0;
2414} /* xc__gc() */
2415
2416
2417static const luaL_Reg xc_methods[] = {
2418 { "getVersion", &xc_getVersion },
2419 { "setVersion", &xc_setVersion },
2420 { "getSerial", &xc_getSerial },
2421 { "setSerial", &xc_setSerial },
2422 { "digest", &xc_digest },
2423 { "getLifetime", &xc_getLifetime },
2424 { "setLifetime", &xc_setLifetime },
2425 { "getIssuer", &xc_getIssuer },
2426 { "setIssuer", &xc_setIssuer },
2427 { "getSubject", &xc_getSubject },
2428 { "setSubject", &xc_setSubject },
2429 { "getIssuerAlt", &xc_getIssuerAlt },
2430 { "setIssuerAlt", &xc_setIssuerAlt },
2431 { "getSubjectAlt", &xc_getSubjectAlt },
2432 { "setSubjectAlt", &xc_setSubjectAlt },
2433 { "getIssuerAltCritical", &xc_getIssuerAltCritical },
2434 { "setIssuerAltCritical", &xc_setIssuerAltCritical },
2435 { "getSubjectAltCritical", &xc_getSubjectAltCritical },
2436 { "setSubjectAltCritical", &xc_setSubjectAltCritical },
2437 { "getBasicConstraints", &xc_getBasicConstraint },
2438 { "getBasicConstraint", &xc_getBasicConstraint },
2439 { "setBasicConstraints", &xc_setBasicConstraint },
2440 { "setBasicConstraint", &xc_setBasicConstraint },
2441 { "getBasicConstraintsCritical", &xc_getBasicConstraintsCritical },
2442 { "setBasicConstraintsCritical", &xc_setBasicConstraintsCritical },
2443 { "isIssuedBy", &xc_isIssuedBy },
2444 { "getPublicKey", &xc_getPublicKey },
2445 { "setPublicKey", &xc_setPublicKey },
2446 { "sign", &xc_sign },
2447 { NULL, NULL },
2448};
2449
2450static const luaL_Reg xc_metatable[] = {
2451 { "__tostring", &xc__tostring },
2452 { "__gc", &xc__gc },
2453 { NULL, NULL },
2454};
2455
2456
2457static const luaL_Reg xc_globals[] = {
2458 { "new", &xc_new },
2459 { "interpose", &xc_interpose },
2460 { NULL, NULL },
2461};
2462
2463int luaopen__openssl_x509_cert(lua_State *L) {
2464 initall(L);
2465
2466 luaL_newlib(L, xc_globals);
2467
2468 return 1;
2469} /* luaopen__openssl_x509_cert() */
2470
2471
2472/*
2473 * X509_REQ - openssl.x509.csr
2474 *
2475 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2476
2477static int xr_new(lua_State *L) {
2478 const char *pem;
2479 size_t len;
2480 X509_REQ **ud;
2481 X509 *crt;
2482
2483 lua_settop(L, 1);
2484
2485 ud = prepsimple(L, X509_CSR_CLASS);
2486
2487 if ((crt = testsimple(L, 1, X509_CERT_CLASS))) {
2488 if (!(*ud = X509_to_X509_REQ(crt, 0, 0)))
2489 return throwssl(L, "x509.csr.new");
2490 } else if ((pem = luaL_optlstring(L, 1, NULL, &len))) {
2491 BIO *tmp;
2492 int ok;
2493
2494 if (!(tmp = BIO_new_mem_buf((char *)pem, len)))
2495 return throwssl(L, "x509.csr.new");
2496
2497 ok = !!PEM_read_bio_X509_REQ(tmp, ud, 0, ""); /* no password */
2498
2499 BIO_free(tmp);
2500
2501 if (!ok)
2502 return throwssl(L, "x509.csr.new");
2503 } else {
2504 if (!(*ud = X509_REQ_new()))
2505 return throwssl(L, "x509.csr.new");
2506 }
2507
2508 return 1;
2509} /* xr_new() */
2510
2511
2512static int xr_interpose(lua_State *L) {
2513 return interpose(L, X509_CSR_CLASS);
2514} /* xr_interpose() */
2515
2516
2517static int xr_getVersion(lua_State *L) {
2518 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2519
2520 lua_pushinteger(L, X509_REQ_get_version(csr) + 1);
2521
2522 return 1;
2523} /* xr_getVersion() */
2524
2525
2526static int xr_setVersion(lua_State *L) {
2527 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2528 int version = luaL_checkint(L, 2);
2529
2530 if (!X509_REQ_set_version(csr, version - 1))
2531 return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version);
2532
2533 lua_pushboolean(L, 1);
2534
2535 return 1;
2536} /* xr_setVersion() */
2537
2538
2539static int xr_getSubject(lua_State *L) {
2540 X509_REQ *crt = checksimple(L, 1, X509_CSR_CLASS);
2541 X509_NAME *name;
2542
2543 if (!(name = X509_REQ_get_subject_name(crt)))
2544 return 0;
2545
2546 xn_dup(L, name);
2547
2548 return 1;
2549} /* xr_getSubject() */
2550
2551
2552static int xr_setSubject(lua_State *L) {
2553 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2554 X509_NAME *name = checksimple(L, 2, X509_NAME_CLASS);
2555
2556 if (!X509_REQ_set_subject_name(csr, name))
2557 return throwssl(L, "x509.csr:setSubject");
2558
2559 lua_pushboolean(L, 1);
2560
2561 return 1;
2562} /* xr_setSubject() */
2563
2564
2565static int xr_getPublicKey(lua_State *L) {
2566 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2567 EVP_PKEY **key = prepsimple(L, PUBKEY_CLASS);
2568
2569 if (!(*key = X509_REQ_get_pubkey(csr)))
2570 return throwssl(L, "x509.cert:getPublicKey");
2571
2572 return 1;
2573} /* xr_getPublicKey() */
2574
2575
2576static int xr_setPublicKey(lua_State *L) {
2577 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2578 EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
2579
2580 if (!X509_REQ_set_pubkey(csr, key))
2581 return throwssl(L, "x509.csr:setPublicKey");
2582
2583 lua_pushboolean(L, 1);
2584
2585 return 1;
2586} /* xr_setPublicKey() */
2587
2588
2589static int xr_sign(lua_State *L) {
2590 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2591 EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
2592
2593 if (!X509_REQ_sign(csr, key, xc_signature(L, 3, key)))
2594 return throwssl(L, "x509.csr:sign");
2595
2596 lua_pushboolean(L, 1);
2597
2598 return 1;
2599} /* xr_sign() */
2600
2601
2602static int xr__tostring(lua_State *L) {
2603 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
2604 int fmt = checkoption(L, 2, "pem", (const char *[]){ "pem", NULL });
2605 BIO *bio = getbio(L);
2606 char *pem;
2607 long len;
2608
2609 if (!PEM_write_bio_X509_REQ(bio, csr))
2610 return throwssl(L, "x509.csr:__tostring");
2611
2612 len = BIO_get_mem_data(bio, &pem);
2613
2614 lua_pushlstring(L, pem, len);
2615
2616 return 1;
2617} /* xr__tostring() */
2618
2619
2620static int xr__gc(lua_State *L) {
2621 X509_REQ **ud = luaL_checkudata(L, 1, X509_CSR_CLASS);
2622
2623 X509_REQ_free(*ud);
2624 *ud = NULL;
2625
2626 return 0;
2627} /* xr__gc() */
2628
2629static const luaL_Reg xr_methods[] = {
2630 { "getVersion", &xr_getVersion },
2631 { "setVersion", &xr_setVersion },
2632 { "getSubject", &xr_getSubject },
2633 { "setSubject", &xr_setSubject },
2634 { "getPublicKey", &xr_getPublicKey },
2635 { "setPublicKey", &xr_setPublicKey },
2636 { "sign", &xr_sign },
2637 { NULL, NULL },
2638};
2639
2640static const luaL_Reg xr_metatable[] = {
2641 { "__tostring", &xr__tostring },
2642 { "__gc", &xr__gc },
2643 { NULL, NULL },
2644};
2645
2646
2647static const luaL_Reg xr_globals[] = {
2648 { "new", &xr_new },
2649 { "interpose", &xr_interpose },
2650 { NULL, NULL },
2651};
2652
2653int luaopen__openssl_x509_csr(lua_State *L) {
2654 initall(L);
2655
2656 luaL_newlib(L, xr_globals);
2657
2658 return 1;
2659} /* luaopen__openssl_x509_csr() */
2660
2661
2662/*
2663 * STACK_OF(X509) - openssl.x509.chain
2664 *
2665 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2666
2667static void xl_dup(lua_State *L, STACK_OF(X509) *src, _Bool copy) {
2668 STACK_OF(X509) **dst = prepsimple(L, X509_CHAIN_CLASS);
2669 X509 *crt;
2670 int i, n;
2671
2672 if (copy) {
2673 if (!(*dst = sk_X509_new_null()))
2674 goto error;
2675
2676 n = sk_X509_num(src);
2677
2678 for (i = 0; i < n; i++) {
2679 if (!(crt = sk_X509_value(src, i)))
2680 continue;
2681
2682 if (!(crt = X509_dup(crt)))
2683 goto error;
2684
2685 if (!sk_X509_push(*dst, crt)) {
2686 X509_free(crt);
2687 goto error;
2688 }
2689 }
2690 } else {
2691 if (!(*dst = sk_X509_dup(src)))
2692 goto error;
2693
2694 n = sk_X509_num(*dst);
2695
2696 for (i = 0; i < n; i++) {
2697 if (!(crt = sk_X509_value(*dst, i)))
2698 continue;
2699 CRYPTO_add(&crt->references, 1, CRYPTO_LOCK_X509);
2700 }
2701 }
2702
2703 return;
2704error:
2705 throwssl(L, "sk_X509_dup");
2706} /* xl_dup() */
2707
2708
2709static int xl_new(lua_State *L) {
2710 STACK_OF(X509) **chain = prepsimple(L, X509_CHAIN_CLASS);
2711
2712 if (!(*chain = sk_X509_new_null()))
2713 return throwssl(L, "x509.chain.new");
2714
2715 return 1;
2716} /* xl_new() */
2717
2718
2719static int xl_interpose(lua_State *L) {
2720 return interpose(L, X509_CHAIN_CLASS);
2721} /* xl_interpose() */
2722
2723
2724static int xl_add(lua_State *L) {
2725 STACK_OF(X509) *chain = checksimple(L, 1, X509_CHAIN_CLASS);
2726 X509 *crt = checksimple(L, 2, X509_CERT_CLASS);
2727 X509 *dup;
2728
2729 if (!(dup = X509_dup(crt)))
2730 return throwssl(L, "x509.chain:add");
2731
2732 if (!sk_X509_push(chain, dup)) {
2733 X509_free(dup);
2734 return throwssl(L, "x509.chain:add");
2735 }
2736
2737 lua_pushboolean(L, 1);
2738
2739 return 1;
2740} /* xl_add() */
2741
2742
2743static int xl__next(lua_State *L) {
2744 STACK_OF(X509) *chain = checksimple(L, lua_upvalueindex(1), X509_CHAIN_CLASS);
2745 int i = lua_tointeger(L, lua_upvalueindex(2));
2746 int n = sk_X509_num(chain);
2747
2748 lua_settop(L, 0);
2749
2750 while (i < n) {
2751 X509 *crt, **ret;
2752
2753 if (!(crt = sk_X509_value(chain, i++)))
2754 continue;
2755
2756 lua_pushinteger(L, i);
2757
2758 ret = prepsimple(L, X509_CERT_CLASS);
2759
2760 if (!(*ret = X509_dup(crt)))
2761 return throwssl(L, "x509.chain:__next");
2762
2763 break;
2764 }
2765
2766 lua_pushinteger(L, i);
2767 lua_replace(L, lua_upvalueindex(2));
2768
2769 return lua_gettop(L);
2770} /* xl__next() */
2771
2772static int xl__pairs(lua_State *L) {
2773 lua_settop(L, 1);
2774 lua_pushinteger(L, 0);
2775 lua_pushcclosure(L, &xl__next, 2);
2776
2777 return 1;
2778} /* xl__pairs() */
2779
2780
2781static int xl__gc(lua_State *L) {
2782 STACK_OF(X509) **chain = luaL_checkudata(L, 1, X509_CHAIN_CLASS);
2783
2784 sk_X509_pop_free(*chain, X509_free);
2785 *chain = NULL;
2786
2787 return 0;
2788} /* xl__gc() */
2789
2790
2791static const luaL_Reg xl_methods[] = {
2792 { "add", &xl_add },
2793 { NULL, NULL },
2794};
2795
2796static const luaL_Reg xl_metatable[] = {
2797 { "__pairs", &xl__pairs },
2798 { "__ipairs", &xl__pairs },
2799 { "__gc", &xl__gc },
2800 { NULL, NULL },
2801};
2802
2803static const luaL_Reg xl_globals[] = {
2804 { "new", &xl_new },
2805 { "interpose", &xl_interpose },
2806 { NULL, NULL },
2807};
2808
2809int luaopen__openssl_x509_chain(lua_State *L) {
2810 initall(L);
2811
2812 luaL_newlib(L, xl_globals);
2813
2814 return 1;
2815} /* luaopen__openssl_x509_chain() */
2816
2817
2818/*
2819 * X509_STORE - openssl.x509.store
2820 *
2821 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2822
2823static int xs_new(lua_State *L) {
2824 X509_STORE **ud = prepsimple(L, X509_STORE_CLASS);
2825
2826 if (!(*ud = X509_STORE_new()))
2827 return throwssl(L, "x509.store");
2828
2829 return 1;
2830} /* xs_new() */
2831
2832
2833static int xs_interpose(lua_State *L) {
2834 return interpose(L, X509_STORE_CLASS);
2835} /* xs_interpose() */
2836
2837
2838static int xs_add(lua_State *L) {
2839 X509_STORE *store = checksimple(L, 1, X509_STORE_CLASS);
2840 int i, top = lua_gettop(L);
2841
2842 for (i = 2; i <= top; i++) {
2843 if (lua_isuserdata(L, i)) {
2844 X509 *crt = checksimple(L, i, X509_CERT_CLASS);
2845 X509 *dup;
2846
2847 if (!(dup = X509_dup(crt)))
2848 return throwssl(L, "x509.store:add");
2849
2850 if (!X509_STORE_add_cert(store, dup)) {
2851 X509_free(dup);
2852 return throwssl(L, "x509.store:add");
2853 }
2854 } else {
2855 const char *path = luaL_checkstring(L, i);
2856 struct stat st;
2857 int ok;
2858
2859 if (0 != stat(path, &st))
2860 return luaL_error(L, "%s: %s", path, strerror(errno));
2861
2862 if (S_ISDIR(st.st_mode))
2863 ok = X509_STORE_load_locations(store, NULL, path);
2864 else
2865 ok = X509_STORE_load_locations(store, path, NULL);
2866
2867 if (!ok)
2868 return throwssl(L, "x509.store:add");
2869 }
2870 }
2871
2872 lua_pushboolean(L, 1);
2873
2874 return 1;
2875} /* xs_add() */
2876
2877
2878static int xs_verify(lua_State *L) {
2879 X509_STORE *store = checksimple(L, 1, X509_STORE_CLASS);
2880 X509 *crt = checksimple(L, 2, X509_CERT_CLASS);
2881 STACK_OF(X509) *chain = NULL, **proof;
2882 X509_STORE_CTX ctx;
2883 int ok, why;
2884
2885 /* pre-allocate space for a successful return */
2886 lua_settop(L, 3);
2887 proof = prepsimple(L, X509_CHAIN_CLASS);
2888
2889 if (!lua_isnoneornil(L, 3)) {
2890 X509 *elm;
2891 int i, n;
2892
2893 if (!(chain = sk_X509_dup(checksimple(L, 3, X509_CHAIN_CLASS))))
2894 return throwssl(L, "x509.store:verify");
2895
2896 n = sk_X509_num(chain);
2897
2898 for (i = 0; i < n; i++) {
2899 if (!(elm = sk_X509_value(chain, i)))
2900 continue;
2901 CRYPTO_add(&elm->references, 1, CRYPTO_LOCK_X509);
2902 }
2903 }
2904
2905 if (!X509_STORE_CTX_init(&ctx, store, crt, chain)) {
2906 sk_X509_pop_free(chain, X509_free);
2907 return throwssl(L, "x509.store:verify");
2908 }
2909
2910 ERR_clear_error();
2911
2912 ok = X509_verify_cert(&ctx);
2913
2914 switch (ok) {
2915 case 1: /* verified */
2916 *proof = X509_STORE_CTX_get1_chain(&ctx);
2917
2918 X509_STORE_CTX_cleanup(&ctx);
2919
2920 if (!*proof)
2921 return throwssl(L, "x509.store:verify");
2922
2923 lua_pushboolean(L, 1);
2924 lua_pushvalue(L, -2);
2925
2926 return 2;
2927 case 0: /* not verified */
2928 why = X509_STORE_CTX_get_error(&ctx);
2929
2930 X509_STORE_CTX_cleanup(&ctx);
2931
2932 lua_pushboolean(L, 0);
2933 lua_pushstring(L, X509_verify_cert_error_string(why));
2934
2935 return 2;
2936 default:
2937 X509_STORE_CTX_cleanup(&ctx);
2938
2939 return throwssl(L, "x509.store:verify");
2940 }
2941} /* xs_verify() */
2942
2943
2944static int xs__gc(lua_State *L) {
2945 X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS);
2946
2947 X509_STORE_free(*ud);
2948 *ud = NULL;
2949
2950 return 0;
2951} /* xs__gc() */
2952
2953
2954static const luaL_Reg xs_methods[] = {
2955 { "add", &xs_add },
2956 { "verify", &xs_verify },
2957 { NULL, NULL },
2958};
2959
2960static const luaL_Reg xs_metatable[] = {
2961 { "__gc", &xs__gc },
2962 { NULL, NULL },
2963};
2964
2965static const luaL_Reg xs_globals[] = {
2966 { "new", &xs_new },
2967 { "interpose", &xs_interpose },
2968 { NULL, NULL },
2969};
2970
2971int luaopen__openssl_x509_store(lua_State *L) {
2972 initall(L);
2973
2974 luaL_newlib(L, xs_globals);
2975
2976 return 1;
2977} /* luaopen__openssl_x509_store() */
2978
2979
2980/*
2981 * X509_STORE_CTX - openssl.x509.store.context
2982 *
2983 * This object is intended to be a temporary container in OpenSSL, so the
2984 * memory management is quite clumsy. In particular, it doesn't take
2985 * ownership of the X509_STORE object, which means the reference must be
2986 * held externally for the life of the X509_STORE_CTX object.
2987 *
2988 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2989#if 0
2990static int stx_new(lua_State *L) {
2991 X509_STORE_CTX **ud = prepsimple(L, X509_STCTX_CLASS);
2992 STACK_OF(X509) *chain;
2993
2994 if (!(*ud = X509_STORE_CTX_new()))
2995 return throwssl(L, "x509.store.context");
2996
2997 return 1;
2998} /* stx_new() */
2999
3000
3001static int stx_interpose(lua_State *L) {
3002 return interpose(L, X509_STCTX_CLASS);
3003} /* stx_interpose() */
3004
3005
3006static int stx_add(lua_State *L) {
3007 X509_STORE_CTX *ctx = checksimple(L, 1, X509_STCTX_CLASS);
3008
3009 return 0;
3010} /* stx_add() */
3011
3012
3013static int stx__gc(lua_State *L) {
3014 X509_STORE **ud = luaL_checkudata(L, 1, X509_STORE_CLASS);
3015
3016 X509_STORE_free(*ud);
3017 *ud = NULL;
3018
3019 return 0;
3020} /* stx__gc() */
3021
3022
3023static const luaL_Reg stx_methods[] = {
3024 { "add", &stx_add },
3025 { NULL, NULL },
3026};
3027
3028static const luaL_Reg stx_metatable[] = {
3029 { "__gc", &stx__gc },
3030 { NULL, NULL },
3031};
3032
3033static const luaL_Reg stx_globals[] = {
3034 { "new", &stx_new },
3035 { "interpose", &stx_interpose },
3036 { NULL, NULL },
3037};
3038
3039int luaopen__openssl_x509_store_context(lua_State *L) {
3040 initall(L);
3041
3042 luaL_newlib(L, stx_globals);
3043
3044 return 1;
3045} /* luaopen__openssl_x509_store_context() */
3046#endif
3047
3048
3049/*
3050 * SSL_CTX - openssl.ssl.context
3051 *
3052 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3053
3054static int sx_new(lua_State *L) {
3055 static const char *opts[] = {
3056 "SSLv2", "SSLv3", "SSLv23", "SSL", "TLSv1", "TLS", NULL
3057 };
3058 /* later versions of SSL declare a const qualifier on the return type */
3059 __typeof__(&TLSv1_client_method) method = &TLSv1_client_method;
3060 _Bool srv;
3061 SSL_CTX **ud;
3062
3063 lua_settop(L, 2);
3064 srv = lua_toboolean(L, 2);
3065
3066 switch (checkoption(L, 1, "TLS", opts)) {
3067#ifndef OPENSSL_NO_SSL2
3068 case 0: /* SSLv2 */
3069 method = (srv)? &SSLv2_server_method : &SSLv2_client_method;
3070 break;
3071#endif
3072 case 1: /* SSLv3 */
3073 method = (srv)? &SSLv3_server_method : &SSLv3_client_method;
3074 break;
3075 case 2: /* SSLv23 */
3076 /* FALL THROUGH */
3077 case 3: /* SSL */
3078 method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
3079 break;
3080 case 4: /* TLSv1 */
3081 /* FALL THROUGH */
3082 case 5: /* TLS */
3083 method = (srv)? &TLSv1_server_method : &TLSv1_client_method;
3084 break;
3085 }
3086
3087 ud = prepsimple(L, SSL_CTX_CLASS);
3088
3089 if (!(*ud = SSL_CTX_new(method())))
3090 return throwssl(L, "ssl.context.new");
3091
3092 return 1;
3093} /* sx_new() */
3094
3095
3096static int sx_interpose(lua_State *L) {
3097 return interpose(L, SSL_CTX_CLASS);
3098} /* sx_interpose() */
3099
3100
3101static int sx_setStore(lua_State *L) {
3102 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3103 X509_STORE *store = checksimple(L, 2, X509_STORE_CLASS);
3104
3105 SSL_CTX_set_cert_store(ctx, store);
3106 CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
3107
3108 lua_pushboolean(L, 1);
3109
3110 return 1;
3111} /* sx_setStore() */
3112
3113
3114static int sx_setVerify(lua_State *L) {
3115 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3116 int mode = luaL_optint(L, 2, -1);
3117 int depth = luaL_optint(L, 3, -1);
3118
3119 if (mode != -1)
3120 SSL_CTX_set_verify(ctx, mode, 0);
3121
3122 if (depth != -1)
3123 SSL_CTX_set_verify_depth(ctx, depth);
3124
3125 lua_pushboolean(L, 1);
3126
3127 return 1;
3128} /* sx_setVerify() */
3129
3130
3131static int sx_getVerify(lua_State *L) {
3132 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3133
3134 lua_pushinteger(L, SSL_CTX_get_verify_mode(ctx));
3135 lua_pushinteger(L, SSL_CTX_get_verify_depth(ctx));
3136
3137 return 2;
3138} /* sx_getVerify() */
3139
3140
3141static int sx_setCertificate(lua_State *L) {
3142 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3143 X509 *crt = X509_dup(checksimple(L, 2, X509_CERT_CLASS));
3144 int ok;
3145
3146 ok = SSL_CTX_use_certificate(ctx, crt);
3147 X509_free(crt);
3148
3149 if (!ok)
3150 return throwssl(L, "ssl.context:setCertificate");
3151
3152 lua_pushboolean(L, 1);
3153
3154 return 1;
3155} /* sx_setCertificate() */
3156
3157
3158static int sx_setPrivateKey(lua_State *L) {
3159 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3160 EVP_PKEY *key = checksimple(L, 2, PUBKEY_CLASS);
3161
3162 /*
3163 * NOTE: No easy way to dup the key, but a shared reference should
3164 * be okay as keys are less mutable than certificates.
3165 */
3166 if (!SSL_CTX_use_PrivateKey(ctx, key))
3167 return throwssl(L, "ssl.context:setPrivateKey");
3168
3169 lua_pushboolean(L, 1);
3170
3171 return 1;
3172} /* sx_setPrivateKey() */
3173
3174
3175static int sx_setCipherList(lua_State *L) {
3176 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
3177 const char *ciphers = luaL_checkstring(L, 2);
3178
3179 if (!SSL_CTX_set_cipher_list(ctx, ciphers))
3180 return throwssl(L, "ssl.context:setCipherList");
3181
3182 lua_pushboolean(L, 1);
3183
3184 return 1;
3185} /* sx_setCipherList() */
3186
3187
3188static int sx__gc(lua_State *L) {
3189 SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS);
3190
3191 SSL_CTX_free(*ud);
3192 *ud = NULL;
3193
3194 return 0;
3195} /* sx__gc() */
3196
3197
3198static const luaL_Reg sx_methods[] = {
3199 { "setStore", &sx_setStore },
3200 { "setVerify", &sx_setVerify },
3201 { "getVerify", &sx_getVerify },
3202 { "setCertificate", &sx_setCertificate },
3203 { "setPrivateKey", &sx_setPrivateKey },
3204 { "setCipherList", &sx_setCipherList },
3205 { NULL, NULL },
3206};
3207
3208static const luaL_Reg sx_metatable[] = {
3209 { "__gc", &sx__gc },
3210 { NULL, NULL },
3211};
3212
3213static const luaL_Reg sx_globals[] = {
3214 { "new", &sx_new },
3215 { "interpose", &sx_interpose },
3216 { NULL, NULL },
3217};
3218
3219int luaopen__openssl_ssl_context(lua_State *L) {
3220 initall(L);
3221
3222 luaL_newlib(L, sx_globals);
3223
3224 lua_pushinteger(L, SSL_VERIFY_NONE);
3225 lua_setfield(L, -2, "VERIFY_NONE");
3226
3227 lua_pushinteger(L, SSL_VERIFY_PEER);
3228 lua_setfield(L, -2, "VERIFY_PEER");
3229
3230 lua_pushinteger(L, SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
3231 lua_setfield(L, -2, "VERIFY_FAIL_IF_NO_PEER_CERT");
3232
3233 lua_pushinteger(L, SSL_VERIFY_CLIENT_ONCE);
3234 lua_setfield(L, -2, "VERIFY_CLIENT_ONCE");
3235
3236 return 1;
3237} /* luaopen__openssl_ssl_context() */
3238
3239
3240/*
3241 * SSL - openssl.ssl
3242 *
3243 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3244
3245static int ssl_new(lua_State *L) {
3246 lua_pushnil(L);
3247
3248 return 1;
3249} /* ssl_new() */
3250
3251
3252static int ssl_interpose(lua_State *L) {
3253 return interpose(L, SSL_CLASS);
3254} /* ssl_interpose() */
3255
3256
3257static int ssl_getPeerCertificate(lua_State *L) {
3258 SSL *ssl = checksimple(L, 1, SSL_CLASS);
3259 X509 **x509 = prepsimple(L, X509_CERT_CLASS);
3260
3261 if (!(*x509 = SSL_get_peer_certificate(ssl)))
3262 return 0;
3263
3264 return 1;
3265} /* ssl_getPeerCertificate() */
3266
3267
3268static int ssl_getPeerChain(lua_State *L) {
3269 SSL *ssl = checksimple(L, 1, SSL_CLASS);
3270 STACK_OF(X509) *chain;
3271
3272 if (!(chain = SSL_get_peer_cert_chain(ssl)))
3273 return 0;
3274
3275 xl_dup(L, chain, 0);
3276
3277 return 1;
3278} /* ssl_getPeerChain() */
3279
3280
3281static int ssl_getCipherInfo(lua_State *L) {
3282 SSL *ssl = checksimple(L, 1, SSL_CLASS);
3283 const SSL_CIPHER *cipher;
3284 char descr[256];
3285
3286 if (!(cipher = SSL_get_current_cipher(ssl)))
3287 return 0;
3288
3289 lua_newtable(L);
3290
3291 lua_pushstring(L, SSL_CIPHER_get_name(cipher));
3292 lua_setfield(L, -2, "name");
3293
3294 lua_pushinteger(L, SSL_CIPHER_get_bits(cipher, 0));
3295 lua_setfield(L, -2, "bits");
3296
3297 lua_pushstring(L, SSL_CIPHER_get_version(cipher));
3298 lua_setfield(L, -2, "version");
3299
3300 lua_pushstring(L, SSL_CIPHER_description(cipher, descr, sizeof descr));
3301 lua_setfield(L, -2, "description");
3302
3303 return 1;
3304} /* ssl_getCipherInfo() */
3305
3306
3307static int ssl__gc(lua_State *L) {
3308 SSL **ud = luaL_checkudata(L, 1, SSL_CLASS);
3309
3310 SSL_free(*ud);
3311 *ud = NULL;
3312
3313 return 0;
3314} /* ssl__gc() */
3315
3316
3317static const luaL_Reg ssl_methods[] = {
3318 { "getPeerCertificate", &ssl_getPeerCertificate },
3319 { "getPeerChain", &ssl_getPeerChain },
3320 { "getCipherInfo", &ssl_getCipherInfo },
3321 { NULL, NULL },
3322};
3323
3324static const luaL_Reg ssl_metatable[] = {
3325 { "__gc", &ssl__gc },
3326 { NULL, NULL },
3327};
3328
3329static const luaL_Reg ssl_globals[] = {
3330 { "new", &ssl_new },
3331 { "interpose", &ssl_interpose },
3332 { NULL, NULL },
3333};
3334
3335int luaopen__openssl_ssl(lua_State *L) {
3336 initall(L);
3337
3338 luaL_newlib(L, ssl_globals);
3339
3340 return 1;
3341} /* luaopen__openssl_ssl() */
3342
3343
3344/*
3345 * Digest - openssl.digest
3346 *
3347 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3348
3349static const EVP_MD *md_optdigest(lua_State *L, int index) {
3350 const char *name = luaL_optstring(L, index, "sha1");
3351 const EVP_MD *type;
3352
3353 if (!(type = EVP_get_digestbyname(name)))
3354 luaL_argerror(L, index, lua_pushfstring(L, "%s: invalid digest type", name));
3355
3356 return type;
3357} /* md_optdigest() */
3358
3359
3360static int md_new(lua_State *L) {
3361 const EVP_MD *type = md_optdigest(L, 1);
3362 EVP_MD_CTX *ctx;
3363
3364 ctx = prepudata(L, sizeof *ctx, DIGEST_CLASS, NULL);
3365
3366 EVP_MD_CTX_init(ctx);
3367
3368 if (!EVP_DigestInit_ex(ctx, type, NULL))
3369 return throwssl(L, "digest.new");
3370
3371 return 1;
3372} /* md_new() */
3373
3374
3375static int md_interpose(lua_State *L) {
3376 return interpose(L, DIGEST_CLASS);
3377} /* md_interpose() */
3378
3379
3380static void md_update_(lua_State *L, EVP_MD_CTX *ctx, int from, int to) {
3381 int i;
3382
3383 for (i = from; i <= to; i++) {
3384 const void *p;
3385 size_t n;
3386
3387 p = luaL_checklstring(L, i, &n);
3388
3389 if (!EVP_DigestUpdate(ctx, p, n))
3390 throwssl(L, "digest:update");
3391 }
3392} /* md_update_() */
3393
3394
3395static int md_update(lua_State *L) {
3396 EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS);
3397 int i, top = lua_gettop(L);
3398
3399 md_update_(L, ctx, 2, lua_gettop(L));
3400
3401 lua_pushboolean(L, 1);
3402
3403 return 1;
3404} /* md_update() */
3405
3406
3407static int md_final(lua_State *L) {
3408 EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS);
3409 unsigned char md[EVP_MAX_MD_SIZE];
3410 unsigned len;
3411
3412 md_update_(L, ctx, 2, lua_gettop(L));
3413
3414 if (!EVP_DigestFinal_ex(ctx, md, &len))
3415 return throwssl(L, "digest:final");
3416
3417 lua_pushlstring(L, (char *)md, len);
3418
3419 return 1;
3420} /* md_final() */
3421
3422
3423static int md__gc(lua_State *L) {
3424 EVP_MD_CTX *ctx = luaL_checkudata(L, 1, DIGEST_CLASS);
3425
3426 EVP_MD_CTX_cleanup(ctx);
3427
3428 return 0;
3429} /* md__gc() */
3430
3431
3432static const luaL_Reg md_methods[] = {
3433 { "update", &md_update },
3434 { "final", &md_final },
3435 { NULL, NULL },
3436};
3437
3438static const luaL_Reg md_metatable[] = {
3439 { "__gc", &md__gc },
3440 { NULL, NULL },
3441};
3442
3443static const luaL_Reg md_globals[] = {
3444 { "new", &md_new },
3445 { "interpose", &md_interpose },
3446 { NULL, NULL },
3447};
3448
3449int luaopen__openssl_digest(lua_State *L) {
3450 initall(L);
3451
3452 luaL_newlib(L, md_globals);
3453
3454 return 1;
3455} /* luaopen__openssl_digest() */
3456
3457
3458/*
3459 * HMAC - openssl.hmac
3460 *
3461 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3462
3463static int hmac_new(lua_State *L) {
3464 const void *key;
3465 size_t len;
3466 const EVP_MD *type;
3467 HMAC_CTX *ctx;
3468
3469 key = luaL_checklstring(L, 1, &len);
3470 type = md_optdigest(L, 2);
3471
3472 ctx = prepudata(L, sizeof *ctx, HMAC_CLASS, NULL);
3473
3474 HMAC_Init_ex(ctx, key, len, type, NULL);
3475
3476 return 1;
3477} /* hmac_new() */
3478
3479
3480static int hmac_interpose(lua_State *L) {
3481 return interpose(L, HMAC_CLASS);
3482} /* hmac_interpose() */
3483
3484
3485static void hmac_update_(lua_State *L, HMAC_CTX *ctx, int from, int to) {
3486 int i;
3487
3488 for (i = from; i <= to; i++) {
3489 const void *p;
3490 size_t n;
3491
3492 p = luaL_checklstring(L, i, &n);
3493
3494 HMAC_Update(ctx, p, n);
3495 }
3496} /* hmac_update_() */
3497
3498
3499static int hmac_update(lua_State *L) {
3500 HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS);
3501
3502 hmac_update_(L, ctx, 2, lua_gettop(L));
3503
3504 lua_pushboolean(L, 1);
3505
3506 return 1;
3507} /* hmac_update() */
3508
3509
3510static int hmac_final(lua_State *L) {
3511 HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS);
3512 unsigned char hmac[EVP_MAX_MD_SIZE];
3513 unsigned len;
3514
3515 hmac_update_(L, ctx, 2, lua_gettop(L));
3516
3517 HMAC_Final(ctx, hmac, &len);
3518
3519 lua_pushlstring(L, (char *)hmac, len);
3520
3521 return 1;
3522} /* hmac_final() */
3523
3524
3525static int hmac__gc(lua_State *L) {
3526 HMAC_CTX *ctx = luaL_checkudata(L, 1, HMAC_CLASS);
3527
3528 HMAC_CTX_cleanup(ctx);
3529
3530 return 0;
3531} /* hmac__gc() */
3532
3533
3534static const luaL_Reg hmac_methods[] = {
3535 { "update", &hmac_update },
3536 { "final", &hmac_final },
3537 { NULL, NULL },
3538};
3539
3540static const luaL_Reg hmac_metatable[] = {
3541 { "__gc", &hmac__gc },
3542 { NULL, NULL },
3543};
3544
3545static const luaL_Reg hmac_globals[] = {
3546 { "new", &hmac_new },
3547 { "interpose", &hmac_interpose },
3548 { NULL, NULL },
3549};
3550
3551int luaopen__openssl_hmac(lua_State *L) {
3552 initall(L);
3553
3554 luaL_newlib(L, hmac_globals);
3555
3556 return 1;
3557} /* luaopen__openssl_hmac() */
3558
3559
3560/*
3561 * Cipher - openssl.cipher
3562 *
3563 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3564
3565static const EVP_CIPHER *cipher_checktype(lua_State *L, int index) {
3566 const char *name = luaL_checkstring(L, index);
3567 const EVP_CIPHER *type;
3568
3569 if (!(type = EVP_get_cipherbyname(name)))
3570 luaL_argerror(L, index, lua_pushfstring(L, "%s: invalid cipher type", name));
3571
3572 return type;
3573} /* cipher_checktype() */
3574
3575
3576static int cipher_new(lua_State *L) {
3577 const EVP_CIPHER *type;
3578 EVP_CIPHER_CTX *ctx;
3579
3580 type = cipher_checktype(L, 1);
3581
3582 ctx = prepudata(L, sizeof *ctx, CIPHER_CLASS, NULL);
3583 EVP_CIPHER_CTX_init(ctx);
3584
3585 if (!EVP_CipherInit_ex(ctx, type, NULL, NULL, NULL, -1))
3586 return throwssl(L, "cipher.new");
3587
3588 return 1;
3589} /* cipher_new() */
3590
3591
3592static int cipher_interpose(lua_State *L) {
3593 return interpose(L, HMAC_CLASS);
3594} /* cipher_interpose() */
3595
3596
3597static int cipher_init(lua_State *L, _Bool encrypt) {
3598 EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS);
3599 const void *key, *iv;
3600 size_t n, m;
3601
3602 key = luaL_checklstring(L, 2, &n);
3603 m = (size_t)EVP_CIPHER_CTX_key_length(ctx);
3604 luaL_argcheck(L, n == m, 2, lua_pushfstring(L, "%d: invalid key length (should be %d)", (int)n, (int)m));
3605
3606 iv = luaL_optlstring(L, 3, NULL, &n);
3607 m = (size_t)EVP_CIPHER_CTX_iv_length(ctx);
3608 luaL_argcheck(L, n == m, 3, lua_pushfstring(L, "%d: invalid IV length (should be %d)", (int)n, (int)m));
3609
3610 if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, encrypt))
3611 goto sslerr;
3612
3613 if (!lua_isnoneornil(L, 4)) {
3614 luaL_checktype(L, 4, LUA_TBOOLEAN);
3615
3616 if (!EVP_CIPHER_CTX_set_padding(ctx, lua_toboolean(L, 4)))
3617 goto sslerr;
3618 }
3619
3620 lua_settop(L, 1);
3621
3622 return 1;
3623sslerr:
3624 return throwssl(L, (encrypt)? "cipher:encrypt" : "cipher:decrypt");
3625} /* cipher_init() */
3626
3627
3628static int cipher_encrypt(lua_State *L) {
3629 return cipher_init(L, 1);
3630} /* cipher_encrypt() */
3631
3632
3633static int cipher_decrypt(lua_State *L) {
3634 return cipher_init(L, 0);
3635} /* cipher_decrypt() */
3636
3637
3638static _Bool cipher_update_(lua_State *L, EVP_CIPHER_CTX *ctx, luaL_Buffer *B, int from, int to) {
3639 const unsigned char *p, *pe;
3640 size_t block, step, n;
3641 int i;
3642
3643 block = EVP_CIPHER_CTX_block_size(ctx);
3644
3645 if (LUAL_BUFFERSIZE < block * 2)
3646 luaL_error(L, "cipher:update: LUAL_BUFFERSIZE(%d) < 2 * EVP_CIPHER_CTX_block_size(%d)", (int)LUAL_BUFFERSIZE, (int)block);
3647
3648 step = LUAL_BUFFERSIZE - block;
3649
3650 for (i = from; i <= to; i++) {
3651 p = (const unsigned char *)luaL_checklstring(L, i, &n);
3652 pe = p + n;
3653
3654 while (p < pe) {
3655 int in = (int)MIN((size_t)(pe - p), step), out;
3656
3657 if (!EVP_CipherUpdate(ctx, (void *)luaL_prepbuffer(B), &out, p, in))
3658 return 0;
3659
3660 p += in;
3661 luaL_addsize(B, out);
3662 }
3663 }
3664
3665 return 1;
3666} /* cipher_update_() */
3667
3668
3669static int cipher_update(lua_State *L) {
3670 EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS);
3671 luaL_Buffer B;
3672
3673 luaL_buffinit(L, &B);
3674
3675 if (!cipher_update_(L, ctx, &B, 2, lua_gettop(L)))
3676 goto sslerr;
3677
3678 luaL_pushresult(&B);
3679
3680 return 1;
3681sslerr:
3682 lua_pushnil(L);
3683 pusherror(L, NULL);
3684
3685 return 2;
3686} /* cipher_update() */
3687
3688
3689static int cipher_final(lua_State *L) {
3690 EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS);
3691 luaL_Buffer B;
3692 size_t block;
3693 int out;
3694
3695 luaL_buffinit(L, &B);
3696
3697 if (!cipher_update_(L, ctx, &B, 2, lua_gettop(L)))
3698 goto sslerr;
3699
3700 block = EVP_CIPHER_CTX_block_size(ctx);
3701
3702 if (LUAL_BUFFERSIZE < block)
3703 return luaL_error(L, "cipher:update: LUAL_BUFFERSIZE(%d) < EVP_CIPHER_CTX_block_size(%d)", (int)LUAL_BUFFERSIZE, (int)block);
3704
3705 if (!EVP_CipherFinal(ctx, (void *)luaL_prepbuffer(&B), &out))
3706 goto sslerr;
3707
3708 luaL_addsize(&B, out);
3709 luaL_pushresult(&B);
3710
3711 return 1;
3712sslerr:
3713 lua_pushnil(L);
3714 pusherror(L, NULL);
3715
3716 return 2;
3717} /* cipher_final() */
3718
3719
3720static int cipher__gc(lua_State *L) {
3721 EVP_CIPHER_CTX *ctx = luaL_checkudata(L, 1, CIPHER_CLASS);
3722
3723 EVP_CIPHER_CTX_cleanup(ctx);
3724
3725 return 0;
3726} /* cipher__gc() */
3727
3728
3729static const luaL_Reg cipher_methods[] = {
3730 { "encrypt", &cipher_encrypt },
3731 { "decrypt", &cipher_decrypt },
3732 { "update", &cipher_update },
3733 { "final", &cipher_final },
3734 { NULL, NULL },
3735};
3736
3737static const luaL_Reg cipher_metatable[] = {
3738 { "__gc", &cipher__gc },
3739 { NULL, NULL },
3740};
3741
3742static const luaL_Reg cipher_globals[] = {
3743 { "new", &cipher_new },
3744 { "interpose", &cipher_interpose },
3745 { NULL, NULL },
3746};
3747
3748int luaopen__openssl_cipher(lua_State *L) {
3749 initall(L);
3750
3751 luaL_newlib(L, cipher_globals);
3752
3753 return 1;
3754} /* luaopen__openssl_cipher() */
3755
3756
3757/*
3758 * Rand - openssl.rand
3759 *
3760 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3761
3762static int rand_bytes(lua_State *L) {
3763 int size = luaL_checkint(L, 1);
3764 luaL_Buffer B;
3765 int count = 0, n;
3766
3767 luaL_buffinit(L, &B);
3768
3769 while (count < size) {
3770 n = MIN((size - count), LUAL_BUFFERSIZE);
3771
3772 if (!RAND_bytes((void *)luaL_prepbuffer(&B), n))
3773 return throwssl(L, "rand.bytes");
3774
3775 luaL_addsize(&B, n);
3776 count += n;
3777 }
3778
3779 luaL_pushresult(&B);
3780
3781 return 1;
3782} /* rand_bytes() */
3783
3784
3785static int rand_ready(lua_State *L) {
3786 lua_pushboolean(L, RAND_status() == 1);
3787
3788 return 1;
3789} /* rand_ready() */
3790
3791
3792static unsigned long long rand_llu(lua_State *L) {
3793 unsigned long long llu;
3794
3795 if (!RAND_bytes((void *)&llu, sizeof llu))
3796 throwssl(L, "rand.uniform");
3797
3798 return llu;
3799} /* rand_llu() */
3800
3801/*
3802 * The following algorithm for rand_uniform() is taken from OpenBSD's
3803 * arc4random_uniform, written by Otto Moerbeek, with subsequent
3804 * simplification by Jorden Verwer. Otto's source code comment reads
3805 *
3806 * Uniformity is achieved by generating new random numbers until the one
3807 * returned is outside the range [0, 2**32 % upper_bound). This guarantees
3808 * the selected random number will be inside [2**32 % upper_bound, 2**32)
3809 * which maps back to [0, upper_bound) after reduction modulo upper_bound.
3810 *
3811 * --
3812 * A more bit-efficient approach by the eminent statistician Herman Rubin
3813 * can be found in this sci.crypt Usenet post.
3814 *
3815 * From: hrubin@odds.stat.purdue.edu (Herman Rubin)
3816 * Newsgroups: sci.crypt
3817 * Subject: Re: Generating a random number between 0 and N-1
3818 * Date: 14 Nov 2002 11:20:37 -0500
3819 * Organization: Purdue University Statistics Department
3820 * Lines: 40
3821 * Message-ID: <ar0igl$1ak2@odds.stat.purdue.edu>
3822 * References: <yO%y9.19646$RO1.373975@weber.videotron.net> <3DCD8D75.40408@nospam.com>
3823 * NNTP-Posting-Host: odds.stat.purdue.edu
3824 * X-Trace: mozo.cc.purdue.edu 1037290837 9316 128.210.141.13 (14 Nov 2002 16:20:37 GMT)
3825 * X-Complaints-To: ne...@news.purdue.edu
3826 * NNTP-Posting-Date: Thu, 14 Nov 2002 16:20:37 +0000 (UTC)
3827 * Xref: archiver1.google.com sci.crypt:78935
3828 *
3829 * In article <3DCD8D7...@nospam.com>,
3830 * Michael Amling <nos...@nospam.com> wrote:
3831 * >Carlos Moreno wrote:
3832 *
3833 * I have already posted on this, but a repeat might be
3834 * in order.
3835 *
3836 * If one can trust random bits, the most bitwise efficient
3837 * manner to get a single random integer between 0 and N-1
3838 * can be obtained as follows; the code can be made more
3839 * computationally efficient. I believe it is easier to
3840 * understand with gotos. I am assuming N>1.
3841 *
3842 * i = 0; j = 1;
3843 *
3844 * loop: j=2*j; i=2*i+RANBIT;
3845 * if (j < N) goto loop;
3846 * if (i >= N) {
3847 * i = i - N;
3848 * j = j - N;
3849 * goto loop:}
3850 * else return (i);
3851 *
3852 * The algorithm works because at each stage i is uniform
3853 * between 0 and j-1.
3854 *
3855 * Another possibility is to generate k bits, where 2^k >= N.
3856 * If 2^k = c*N + remainder, generate the appropriate value
3857 * if a k-bit random number is less than c*N.
3858 *
3859 * For N = 17 (numbers just larger than powers of 2 are "bad"),
3860 * the amount of information is about 4.09 bits, the best
3861 * algorithm to generate one random number takes about 5.765
3862 * bits, taking k = 5 uses 9.412 bits, taking k = 6 or 7 uses
3863 * 7.529 bits. These are averages, but the tails are not bad.
3864 *
3865 * (https://groups.google.com/forum/message/raw?msg=sci.crypt/DMslf6tSrD8/rv9rk6oP3r4J)
3866 */
3867static int rand_uniform(lua_State *L) {
3868 if (lua_isnoneornil(L, 1)) {
3869 unsigned long long r = rand_llu(L);
3870
3871 lua_pushnumber(L, r);
3872
3873 return 1;
3874 } else {
3875 unsigned long long N = luaL_checknumber(L, 1);
3876 unsigned long long r, m;
3877
3878 luaL_argcheck(L, N > 1, 1, lua_pushfstring(L, "[0, %d): interval is empty", (int)N));
3879
3880 m = -N % N;
3881
3882 do {
3883 r = rand_llu(L);
3884 } while (r < m);
3885
3886 lua_pushnumber(L, (r % N));
3887
3888 return 1;
3889 }
3890} /* rand_uniform() */
3891
3892
3893static const luaL_Reg rand_globals[] = {
3894 { "bytes", &rand_bytes },
3895 { "ready", &rand_ready },
3896 { "uniform", &rand_uniform },
3897 { NULL, NULL },
3898};
3899
3900int luaopen__openssl_rand(lua_State *L) {
3901 initall(L);
3902
3903 luaL_newlib(L, rand_globals);
3904
3905 return 1;
3906} /* luaopen__openssl_rand() */
3907
3908
3909static void initall(lua_State *L) {
3910 ERR_load_crypto_strings();
3911 OpenSSL_add_all_algorithms();
3912
3913 addclass(L, BIGNUM_CLASS, bn_methods, bn_metatable);
3914 addclass(L, PUBKEY_CLASS, pk_methods, pk_metatable);
3915 addclass(L, X509_NAME_CLASS, xn_methods, xn_metatable);
3916 addclass(L, X509_GENS_CLASS, gn_methods, gn_metatable);
3917 addclass(L, X509_CERT_CLASS, xc_methods, xc_metatable);
3918 addclass(L, X509_CSR_CLASS, xr_methods, xr_metatable);
3919 addclass(L, X509_CHAIN_CLASS, xl_methods, xl_metatable);
3920 addclass(L, X509_STORE_CLASS, xs_methods, xs_metatable);
3921 addclass(L, SSL_CTX_CLASS, sx_methods, sx_metatable);
3922 addclass(L, SSL_CLASS, ssl_methods, ssl_metatable);
3923 addclass(L, DIGEST_CLASS, md_methods, md_metatable);
3924 addclass(L, HMAC_CLASS, hmac_methods, hmac_metatable);
3925 addclass(L, CIPHER_CLASS, cipher_methods, cipher_metatable);
3926} /* initall() */
3927
3928
3929#endif /* L_OPENSSL_H */
diff --git a/src/openssl.cipher.lua b/src/openssl.cipher.lua
new file mode 100644
index 0000000..876cd1b
--- /dev/null
+++ b/src/openssl.cipher.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.cipher"
2
3return ctx
diff --git a/src/openssl.digest.lua b/src/openssl.digest.lua
new file mode 100644
index 0000000..87cc958
--- /dev/null
+++ b/src/openssl.digest.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.digest"
2
3return ctx
diff --git a/src/openssl.hmac.lua b/src/openssl.hmac.lua
new file mode 100644
index 0000000..e622d1d
--- /dev/null
+++ b/src/openssl.hmac.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.hmac"
2
3return ctx
diff --git a/src/openssl.pubkey.lua b/src/openssl.pubkey.lua
new file mode 100644
index 0000000..6dc5614
--- /dev/null
+++ b/src/openssl.pubkey.lua
@@ -0,0 +1,4 @@
1local pubkey = require"_openssl.pubkey"
2
3return pubkey
4
diff --git a/src/openssl.rand.lua b/src/openssl.rand.lua
new file mode 100644
index 0000000..70e9d3f
--- /dev/null
+++ b/src/openssl.rand.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.rand"
2
3return ctx
diff --git a/src/openssl.ssl.context.lua b/src/openssl.ssl.context.lua
new file mode 100644
index 0000000..44a9163
--- /dev/null
+++ b/src/openssl.ssl.context.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.ssl.context"
2
3return ctx
diff --git a/src/openssl.ssl.lua b/src/openssl.ssl.lua
new file mode 100644
index 0000000..3c348f6
--- /dev/null
+++ b/src/openssl.ssl.lua
@@ -0,0 +1,3 @@
1local ctx = require"_openssl.ssl"
2
3return ctx
diff --git a/src/openssl.x509.altname.lua b/src/openssl.x509.altname.lua
new file mode 100644
index 0000000..66f16e7
--- /dev/null
+++ b/src/openssl.x509.altname.lua
@@ -0,0 +1,13 @@
1local altname = require"_openssl.x509.altname"
2
3altname.interpose("__tostring", function (self)
4 local t = { }
5
6 for k, v in pairs(self) do
7 t[#t + 1] = k .. ":" .. v
8 end
9
10 return table.concat(t, ", ")
11end)
12
13return altname
diff --git a/src/openssl.x509.chain.lua b/src/openssl.x509.chain.lua
new file mode 100644
index 0000000..e89dec8
--- /dev/null
+++ b/src/openssl.x509.chain.lua
@@ -0,0 +1,3 @@
1local chain = require"_openssl.x509.chain"
2
3return chain
diff --git a/src/openssl.x509.lua b/src/openssl.x509.lua
new file mode 100644
index 0000000..278baf5
--- /dev/null
+++ b/src/openssl.x509.lua
@@ -0,0 +1,3 @@
1local x509 = require"_openssl.x509.cert"
2
3return x509
diff --git a/src/openssl.x509.name.lua b/src/openssl.x509.name.lua
new file mode 100644
index 0000000..a531502
--- /dev/null
+++ b/src/openssl.x509.name.lua
@@ -0,0 +1,13 @@
1local name = require"_openssl.x509.name"
2
3name.interpose("__tostring", function (self)
4 local t = { }
5
6 for k, v in pairs(self) do
7 t[#t + 1] = k .. "=" .. v
8 end
9
10 return table.concat(t, ", ")
11end)
12
13return name
diff --git a/src/openssl.x509.store.lua b/src/openssl.x509.store.lua
new file mode 100644
index 0000000..a717870
--- /dev/null
+++ b/src/openssl.x509.store.lua
@@ -0,0 +1,3 @@
1local store = require"_openssl.x509.store"
2
3return store