Software /
code /
prosody
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 |