Comparison

util-src/crand.c @ 7187:3d2c2f0809ee

util.crand: C binding to one of OpenSSL, Linux getrandom() or OpenBSD arc4random() CSPRNG
author Kim Alvefur <zash@zash.se>
date Mon, 22 Feb 2016 18:44:43 +0100
child 7189:72839cafdf36
comparison
equal deleted inserted replaced
7186:9c3930bcbb72 7187:3d2c2f0809ee
1 /* Prosody IM
2 -- Copyright (C) 2008-2016 Matthew Wild
3 -- Copyright (C) 2008-2016 Waqas Hussain
4 -- Copyright (C) 2016 Kim Alvefur
5 --
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
8 --
9 */
10
11 /*
12 * crand.c
13 * C PRNG interface
14 */
15
16 #include "lualib.h"
17 #include "lauxlib.h"
18
19 #include <string.h>
20 #include <errno.h>
21
22 /*
23 * TODO: Decide on fixed size or dynamically allocated buffer
24 */
25 #if 1
26 #include <malloc.h>
27 #else
28 #define BUFLEN 256
29 #endif
30
31 #if defined(WITH_GETRANDOM)
32 #include <unistd.h>
33 #include <sys/syscall.h>
34 #include <linux/random.h>
35
36 #ifndef SYS_getrandom
37 #error getrandom() requires Linux 3.17 or later
38 #endif
39
40 /* Was this not supposed to be a function? */
41 int getrandom(char *buf, size_t len, int flags) {
42 return syscall(SYS_getrandom, buf, len, flags);
43 }
44
45 #elif defined(WITH_ARC4RANDOM)
46 #include <stdlib.h>
47 #elif defined(WITH_OPENSSL)
48 #include <openssl/rand.h>
49 #else
50 #error util.crand compiled without a random source
51 #endif
52
53 int Lrandom(lua_State *L) {
54 #ifdef BUFLEN
55 unsigned char buf[BUFLEN];
56 #else
57 unsigned char *buf;
58 #endif
59 int ret = 0;
60 size_t len = (size_t)luaL_checkint(L, 1);
61 #ifdef BUFLEN
62 len = len > BUFLEN ? BUFLEN : len;
63 #else
64 buf = malloc(len);
65
66 if(buf == NULL) {
67 lua_pushnil(L);
68 lua_pushstring(L, "out of memory");
69 /* or it migth be better to
70 * return lua_error(L);
71 */
72 return 2;
73 }
74 #endif
75
76 #if defined(WITH_GETRANDOM)
77 ret = getrandom(buf, len, 0);
78
79 if(ret < 0) {
80 #ifndef BUFLEN
81 free(buf);
82 #endif
83 lua_pushnil(L);
84 lua_pushstring(L, strerror(errno));
85 lua_pushinteger(L, errno);
86 return 3;
87 }
88
89 #elif defined(WITH_ARC4RANDOM)
90 arc4random_buf(buf, len);
91 ret = len;
92 #elif defined(WITH_OPENSSL)
93 ret = RAND_bytes(buf, len);
94
95 if(ret == 1) {
96 ret = len;
97 } else {
98 #ifndef BUFLEN
99 free(buf);
100 #endif
101 lua_pushnil(L);
102 lua_pushstring(L, "failed");
103 /* lua_pushinteger(L, ERR_get_error()); */
104 return 2;
105 }
106
107 #endif
108
109 lua_pushlstring(L, buf, ret);
110 #ifndef BUFLEN
111 free(buf);
112 #endif
113 return 1;
114 }
115
116 #ifdef ENABLE_SEEDING
117 int Lseed(lua_State *L) {
118 size_t len;
119 const char *seed = lua_tolstring(L, 1, &len);
120
121 #if defined(WITH_OPENSSL)
122 RAND_add(seed, len, len);
123 return 0;
124 #else
125 lua_pushnil(L);
126 lua_pushliteral(L, "not-supported");
127 return 2;
128 #endif
129 }
130 #endif
131
132 int luaopen_util_crand(lua_State *L) {
133 lua_newtable(L);
134 lua_pushcfunction(L, Lrandom);
135 lua_setfield(L, -2, "bytes");
136 #ifdef ENABLE_SEEDING
137 lua_pushcfunction(L, Lseed);
138 lua_setfield(L, -2, "seed");
139 #endif
140
141 #if defined(WITH_GETRANDOM)
142 lua_pushstring(L, "Linux");
143 #elif defined(WITH_ARC4RANDOM)
144 lua_pushstring(L, "arc4random()");
145 #elif defined(WITH_OPENSSL)
146 lua_pushstring(L, "OpenSSL");
147 #endif
148 lua_setfield(L, -2, "_source");
149
150 #if defined(WITH_OPENSSL) && defined(_WIN32)
151 /* Do we need to seed this on Windows? */
152 #endif
153
154 return 1;
155 }
156