summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/openssl.c227
1 files changed, 207 insertions, 20 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 432c683..967665f 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -26,23 +26,32 @@
26#ifndef LUAOSSL_H 26#ifndef LUAOSSL_H
27#define LUAOSSL_H 27#define LUAOSSL_H
28 28
29#include <limits.h> /* INT_MAX INT_MIN */ 29#include <limits.h> /* INT_MAX INT_MIN */
30#include <string.h> /* memset(3) */ 30#include <string.h> /* memset(3) strerror_r(3) */
31#include <strings.h> /* strcasecmp(3) */ 31#include <strings.h> /* strcasecmp(3) */
32#include <math.h> /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(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) */ 33#include <time.h> /* struct tm time_t strptime(3) */
34#include <ctype.h> /* tolower(3) */ 34#include <ctype.h> /* tolower(3) */
35#include <errno.h> /* errno */
35 36
36#include <sys/types.h> 37#include <sys/types.h> /* ssize_t pid_t */
37#include <sys/stat.h> /* struct stat stat(2) */ 38#include <sys/sysctl.h> /* CTL_KERN KERN_RANDOM RANDOM_UUID KERN_URND KERN_ARND sysctl(2) */
38#include <sys/socket.h> /* AF_INET AF_INET6 */ 39#include <sys/time.h> /* struct timeval gettimeofday(2) */
40#include <sys/stat.h> /* struct stat stat(2) */
41#include <sys/socket.h> /* AF_INET AF_INET6 */
42#include <sys/resource.h> /* RUSAGE_SELF struct rusage getrusage(2) */
43#include <sys/utsname.h> /* struct utsname uname(3) */
39 44
40#include <netinet/in.h> /* struct in_addr struct in6_addr */ 45#include <fcntl.h> /* O_RDONLY O_CLOEXEC open(2) */
41#include <arpa/inet.h> /* inet_pton(3) */
42 46
43#include <pthread.h> /* pthread_mutex_init(3) pthread_mutex_lock(3) pthread_mutex_unlock(3) */ 47#include <unistd.h> /* close(2) getpid(2) */
44 48
45#include <dlfcn.h> /* dladdr(3) dlopen(3) */ 49#include <netinet/in.h> /* struct in_addr struct in6_addr */
50#include <arpa/inet.h> /* inet_pton(3) */
51
52#include <pthread.h> /* pthread_mutex_init(3) pthread_mutex_lock(3) pthread_mutex_unlock(3) */
53
54#include <dlfcn.h> /* dladdr(3) dlopen(3) */
46 55
47#include <openssl/err.h> 56#include <openssl/err.h>
48#include <openssl/bn.h> 57#include <openssl/bn.h>
@@ -107,6 +116,56 @@
107#define HAI SAY("hai") 116#define HAI SAY("hai")
108 117
109 118
119#define xitoa_putc(c) do { if (p < lim) dst[p] = (c); p++; } while (0)
120
121static const char *xitoa(char *dst, size_t lim, long i) {
122 size_t p = 0;
123 unsigned long d = 1000000000UL, n = 0, r;
124
125 if (i < 0) {
126 xitoa_putc('-');
127 i *= -1;
128 }
129
130 if ((i = MIN(2147483647L, i))) {
131 do {
132 if ((r = i / d) || n) {
133 i -= r * d;
134 n++;
135 xitoa_putc('0' + r);
136 }
137 } while (d /= 10);
138 } else {
139 xitoa_putc('0');
140 }
141
142 if (lim)
143 dst[MIN(p, lim - 1)] = '\0';
144
145 return dst;
146} /* xitoa() */
147
148
149#define xstrerror(error) xstrerror_r((error), (char[256]){ 0 }, 256)
150
151static const char *xstrerror_r(int error, char *dst, size_t lim) {
152 static const char unknown[] = "Unknown error: ";
153 size_t n;
154
155 if (0 == strerror_r(error, dst, lim) && *dst != '\0')
156 return dst;
157
158 /*
159 * glibc snprintf can fail on memory pressure, so format our number
160 * manually.
161 */
162 n = MIN(sizeof unknown - 1, lim);
163 memcpy(dst, unknown, n);
164
165 return xitoa(&dst[n], lim - n, error);
166} /* xstrerror_r() */
167
168
110static void *prepudata(lua_State *L, size_t size, const char *tname, int (*gc)(lua_State *)) { 169static void *prepudata(lua_State *L, size_t size, const char *tname, int (*gc)(lua_State *)) {
111 void *p = memset(lua_newuserdata(L, size), 0, size); 170 void *p = memset(lua_newuserdata(L, size), 0, size);
112 171
@@ -3017,7 +3076,7 @@ static int xs_add(lua_State *L) {
3017 int ok; 3076 int ok;
3018 3077
3019 if (0 != stat(path, &st)) 3078 if (0 != stat(path, &st))
3020 return luaL_error(L, "%s: %s", path, strerror(errno)); 3079 return luaL_error(L, "%s: %s", path, xstrerror(errno));
3021 3080
3022 if (S_ISDIR(st.st_mode)) 3081 if (S_ISDIR(st.st_mode))
3023 ok = X509_STORE_load_locations(store, NULL, path); 3082 ok = X509_STORE_load_locations(store, NULL, path);
@@ -3919,6 +3978,137 @@ int luaopen__openssl_cipher(lua_State *L) {
3919 * 3978 *
3920 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3979 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3921 3980
3981#ifndef HAVE_RANDOM_UUID
3982#define HAVE_RANDOM_UUID (defined __linux) /* RANDOM_UUID is an enum, not macro */
3983#endif
3984
3985#ifndef HAVE_KERN_URND
3986#define HAVE_KERN_URND (defined KERN_URND)
3987#endif
3988
3989#ifndef HAVE_KERN_ARND
3990#define HAVE_KERN_ARND (defined KERN_ARND)
3991#endif
3992
3993static int stir(unsigned rqstd) {
3994 unsigned count = 0;
3995 int error;
3996 unsigned char data[256];
3997#if HAVE_RANDOM_UUID || HAVE_KERN_URND || HAVE_KERN_ARND
3998#if HAVE_RANDOM_UUID
3999 int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
4000#elif HAVE_KERN_URND
4001 int mib[] = { CTL_KERN, KERN_URND };
4002#else
4003 int mib[] = { CTL_KERN, KERN_ARND };
4004#endif
4005
4006 while (count < rqstd) {
4007 size_t n = MIN(rqstd - count, sizeof data);
4008
4009 if (0 != sysctl(mib, countof(mib), data, &n, (void *)0, 0))
4010 break;
4011
4012 RAND_add(data, n, n);
4013
4014 count += n;
4015 }
4016#endif
4017
4018 if (count < rqstd) {
4019#if defined O_CLOEXEC
4020 int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
4021#else
4022 int fd = open("/dev/urandom", O_RDONLY);
4023#endif
4024
4025 if (fd == -1)
4026 goto syserr;
4027
4028 while (count < rqstd) {
4029 ssize_t n = read(fd, data, MIN(rqstd - count, sizeof data));
4030
4031 switch (n) {
4032 case 0:
4033 errno = EIO;
4034
4035 /* FALL THROUGH */
4036 case -1:
4037 if (errno == EINTR)
4038 continue;
4039
4040 error = errno;
4041
4042 close(fd);
4043
4044 goto error;
4045 default:
4046 RAND_add(data, n, n);
4047
4048 count += n;
4049 }
4050 }
4051
4052 close(fd);
4053 }
4054
4055 return 0;
4056syserr:
4057 error = errno;
4058error:;
4059 struct {
4060 struct timeval tv;
4061 pid_t pid;
4062 struct rusage ru;
4063 struct utsname un;
4064 int (*fn)();
4065 } junk;
4066
4067 gettimeofday(&junk.tv, NULL);
4068 junk.pid = getpid();
4069 getrusage(RUSAGE_SELF, &junk.ru);
4070 uname(&junk.un);
4071 junk.fn = &stir;
4072
4073 RAND_add(&junk, sizeof junk, 0.1);
4074
4075 return error;
4076} /* stir() */
4077
4078
4079static int rand_stir(lua_State *L) {
4080 int error = stir(luaL_optunsigned(L, 1, 16));
4081
4082 if (error) {
4083 lua_pushboolean(L, 0);
4084 lua_pushstring(L, xstrerror(error));
4085 lua_pushinteger(L, error);
4086
4087 return 3;
4088 } else {
4089 lua_pushboolean(L, 1);
4090
4091 return 1;
4092 }
4093} /* rand_stir() */
4094
4095
4096static int rand_add(lua_State *L) {
4097 const void *buf;
4098 size_t len;
4099 lua_Number entropy;
4100
4101 buf = luaL_checklstring(L, 1, &len);
4102 entropy = luaL_optnumber(L, 2, len);
4103
4104 RAND_add(buf, len, entropy);
4105
4106 lua_pushboolean(L, 1);
4107
4108 return 1;
4109} /* rand_add() */
4110
4111
3922static int rand_bytes(lua_State *L) { 4112static int rand_bytes(lua_State *L) {
3923 int size = luaL_checkint(L, 1); 4113 int size = luaL_checkint(L, 1);
3924 luaL_Buffer B; 4114 luaL_Buffer B;
@@ -4060,6 +4250,8 @@ static int rand_uniform(lua_State *L) {
4060 4250
4061 4251
4062static const luaL_Reg rand_globals[] = { 4252static const luaL_Reg rand_globals[] = {
4253 { "stir", &rand_stir },
4254 { "add", &rand_add },
4063 { "bytes", &rand_bytes }, 4255 { "bytes", &rand_bytes },
4064 { "ready", &rand_ready }, 4256 { "ready", &rand_ready },
4065 { "uniform", &rand_uniform }, 4257 { "uniform", &rand_uniform },
@@ -4194,12 +4386,7 @@ static void initall(lua_State *L) {
4194 if (error == -1) { 4386 if (error == -1) {
4195 luaL_error(L, "openssl.init: %s", dlerror()); 4387 luaL_error(L, "openssl.init: %s", dlerror());
4196 } else { 4388 } else {
4197 char why[256]; 4389 luaL_error(L, "openssl.init: %s", xstrerror(error));
4198
4199 if (0 != strerror_r(error, why, sizeof why) || *why == '\0')
4200 luaL_error(L, "openssl.init: Unknown error: %d", error);
4201
4202 luaL_error(L, "openssl.init: %s", why);
4203 } 4390 }
4204 } 4391 }
4205 4392