Skip to content

Commit

Permalink
fix: prevent NaN and positive / negative infinity values on random nu…
Browse files Browse the repository at this point in the history
…mber.
  • Loading branch information
luau-project committed Jan 18, 2025
1 parent 52569fb commit 5366e0c
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
- "docs/**"

env:
ROCKSPEC_VERSION: 0.0.1
ROCKSPEC_VERSION: 0.0.2
DEV_ROCKSPEC: lua-cryptorandom-dev-1.rockspec

jobs:
Expand Down
3 changes: 2 additions & 1 deletion Makefile.macosx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ OBJ_EXTENSION = o
LIB_EXTENSION = so
CFLAGS_EXTRA = -DLUA_CRYPTORANDOM_BUILD_SHARED -DLUA_CRYPTORANDOM_USE_APPLE
LIBFLAG_EXTRA = -framework Security
LIB_M = -lm

LUA_DIR = /usr/local
LUA_INCDIR = $(LUA_DIR)/include
Expand All @@ -13,7 +14,7 @@ INSTALL_LIBDIR = $(INSTALL_PREFIX)/lib/lua/$(LUA_VERSION)
all: src/lua-cryptorandom.$(LIB_EXTENSION)

src/lua-cryptorandom.$(LIB_EXTENSION): src/lua-cryptorandom.$(OBJ_EXTENSION)
$(CC) $(LIBFLAG_EXTRA) $(LIBFLAG) -o $@ $<
$(CC) $(LIBFLAG_EXTRA) $(LIBFLAG) -o $@ $< $(LIB_M)

src/lua-cryptorandom.$(OBJ_EXTENSION): src/lua-cryptorandom.c
$(CC) -c $(CFLAGS_EXTRA) $(CFLAGS) -I$(LUA_INCDIR) $< -o $@
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
>
> ```lua-cryptorandom``` is implemented in C, and also compiles as C++.
> [!WARNING]
>
> Are you using a personalized compilation of Lua? See the [known limitations](#known-limitations).
## Use cases

Many security operations rely on the high-quality of randomization services to avoid reproducibility and remain resistant to reverse engineering:
Many security operations rely on high-quality randomization services to avoid reproducibility and remain resistant to reverse engineering:

* randomized password generation;
* nonces (numbers used once) generation;
Expand Down Expand Up @@ -137,6 +133,7 @@ luarocks install lua-cryptorandom
* *Return*: ```number | nil``` as first value, and ```nil | integer``` as the second.
* ```number | nil```: the generated float number on success, or ```nil``` when an error occurred;
* ```nil | integer```: an error code that is set to ```nil``` on success, or an ```integer``` representing the code used by the underlying library (```OpenSSL``` on Unix, ```bcrypt``` on Windows and ```Security``` framework on macOS / iOS).
* *Remark*: since v0.0.2, in case of success, the returned number is not ```NaN``` or positive/negative infinity values.
* *Usage*:

```lua
Expand Down Expand Up @@ -175,11 +172,16 @@ luarocks install lua-cryptorandom

## Known limitations

* The error code (second return value) on each method might deliver a value different than the one returned by the underlying library. This condition might happen when the Lua type ```lua_Integer``` is shorter than an ```unsigned long``` in size. Even though it can be achieved on personalized compilations of Lua (e.g.: Lua compiled as ANSI C), the usual build of Lua should be safe for most users and platforms.
> [!WARNING]
>
> This section mostly applies to users running a customized build of Lua.

* The error code (second return value) on each method might deliver a value different than the one returned by the underlying library. This condition might happen when the Lua type ```lua_Integer``` is shorter than an ```unsigned long``` in size. Even though it can be achieved on personalized builds of Lua (e.g.: Lua compiled as ANSI C on some platforms), the usual build of Lua should be safe for most users and platforms.

## Change log

v0.0.1: Initial release.
* v0.0.2: Prevent the generation of ```NaN``` and positive/negative infinity values in the function [number](#number).
* v0.0.1: Initial release.

## Future works

Expand Down
105 changes: 105 additions & 0 deletions rockspecs/lua-cryptorandom-0.0.2-1.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package = "lua-cryptorandom"
version = "0.0.2-1"

source = {
url = "git+https://github.com/luau-project/lua-cryptorandom",
tag = "v0.0.2"
}

description = {
homepage = "https://github.com/luau-project/lua-cryptorandom",
summary = [[Generate cryptographically secure pseudo random numbers for Lua]],
detailed = [=[
lua-cryptorandom is a lightweight, native library for Lua aimed to generate cryptographically secure pseudo random numbers, using trusted sources of randomness provided by the operating system.
Visit the repository for more information.]=],
license = "MIT"
}

dependencies = {
"lua >= 5.1"
}

local function external_dependencies_plat()
return {
["CRYPTO"] = {
header = "openssl/rand.h"
}
}
end

external_dependencies = {
platforms = {
linux = external_dependencies_plat(),
freebsd = external_dependencies_plat(),
openbsd = external_dependencies_plat(),
netbsd = external_dependencies_plat(),
dragonfly = external_dependencies_plat()
}
}

local function build_plat(plat)
if (plat == "macosx" or plat == "macos") then
return {
type = "make",
makefile = "Makefile.macosx",
build_variables = {
CFLAGS = "$(CFLAGS)",
LIBFLAG = "$(LIBFLAG)",
CFLAGS_EXTRA = "-DLUA_CRYPTORANDOM_BUILD_SHARED -DLUA_CRYPTORANDOM_USE_APPLE",
LIBFLAG_EXTRA = "-framework Security",
LUA_INCDIR = "$(LUA_INCDIR)",
OBJ_EXTENSION = "$(OBJ_EXTENSION)",
LIB_EXTENSION = "$(LIB_EXTENSION)"
},
install_variables = {
INSTALL_PREFIX = "$(PREFIX)",
INSTALL_LIBDIR = "$(LIBDIR)",
LUA_VERSION = "$(LUA_VERSION)",
LIB_EXTENSION = "$(LIB_EXTENSION)"
}
}
elseif (plat == "windows" or plat == "cygwin") then
return {
type = "builtin",
modules = {
["lua-cryptorandom"] = {
sources = { "src/lua-cryptorandom.c" },
libraries = { "bcrypt" },
defines = { "LUA_CRYPTORANDOM_BUILD_SHARED", "LUA_CRYPTORANDOM_USE_WIN32" },
incdirs = { "src" },
libdirs = { }
}
}
}
elseif (plat == "linux" or plat == "bsd") then
return {
type = "builtin",
modules = {
["lua-cryptorandom"] = {
sources = { "src/lua-cryptorandom.c" },
libraries = { "crypto" },
defines = { "LUA_CRYPTORANDOM_BUILD_SHARED", "LUA_CRYPTORANDOM_USE_OPENSSL" },
incdirs = { "src", "$(CRYPTO_INCDIR)" },
libdirs = { "$(CRYPTO_LIBDIR)" }
}
}
}
else
error("Unknown platform", 2)
end
end

build = {
platforms = {
macosx = build_plat("macosx"),
macos = build_plat("macos"),
windows = build_plat("windows"),
cygwin = build_plat("cygwin"),
linux = build_plat("linux"),
freebsd = build_plat("bsd"),
openbsd = build_plat("bsd"),
netbsd = build_plat("bsd"),
dragonfly = build_plat("bsd")
}
}
70 changes: 54 additions & 16 deletions src/lua-cryptorandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,42 @@
#endif

#include <stdlib.h>
#include <math.h>

#include <luaconf.h>
#include <lauxlib.h>
#include <lualib.h>

#ifndef isnan
#define isnan(x) (!((x)==(x)))
#endif

#ifndef isinf
#define isinf(x) ((x)==(HUGE_VAL)?(1):((x)==(-HUGE_VAL)?(-1):(0)))
#endif

/*
** helper union to the function
** lua_cryptorandom_integer
*/
typedef union tagLuaCryptoRandomInteger
{
lua_Integer value;
unsigned char buffer[sizeof(lua_Integer)];

} LuaCryptoRandomInteger;

/*
** helper union to the function
** lua_cryptorandom_number
*/
typedef union tagLuaCryptoRandomNumber
{
lua_Number value;
unsigned char buffer[sizeof(lua_Number)];

} LuaCryptoRandomNumber;

#define LUA_CRYPTORANDOM_METATABLE "lua_cryptorandom_metatable"

/* Implementation to generate cryptographically secure pseudo random bytes */
Expand Down Expand Up @@ -112,18 +144,17 @@ static int lua_cryptorandom_take(lua_State *L)

static int lua_cryptorandom_integer(lua_State *L)
{
unsigned char buffer[sizeof(lua_Integer)];
LuaCryptoRandomInteger rint;

unsigned long err;
if (lua_cryptorandom_bytes_impl(L, (unsigned char *)buffer, sizeof(lua_Integer), &err) == 0)
if (lua_cryptorandom_bytes_impl(L, (unsigned char *)(rint.buffer), sizeof(lua_Integer), &err) == 0)
{
lua_pushnil(L);
lua_pushinteger(L, (lua_Integer)err);
}
else
{
lua_Integer *take_ptr = (lua_Integer *)buffer;
lua_pushinteger(L, *take_ptr);
lua_pushinteger(L, rint.value);
lua_pushnil(L);
}

Expand All @@ -132,21 +163,28 @@ static int lua_cryptorandom_integer(lua_State *L)

static int lua_cryptorandom_number(lua_State *L)
{
unsigned char buffer[sizeof(lua_Number)];

LuaCryptoRandomNumber rnum;
unsigned long err;
if (lua_cryptorandom_bytes_impl(L, (unsigned char *)buffer, sizeof(lua_Number), &err) == 0)
{
lua_pushnil(L);
lua_pushinteger(L, (lua_Integer)err);
}
else

int is_nan_or_inf = 1;
int had_error = 0;

while (!had_error && is_nan_or_inf)
{
lua_Number *take_ptr = (lua_Number *)buffer;
lua_pushnumber(L, *take_ptr);
lua_pushnil(L);
if (lua_cryptorandom_bytes_impl(L, (unsigned char *)(rnum.buffer), sizeof(lua_Number), &err) == 0)
{
lua_pushnil(L);
lua_pushinteger(L, (lua_Integer)err);
had_error = 1;
}
else if (!(isnan(rnum.value) || isinf(rnum.value)))
{
lua_pushnumber(L, rnum.value);
lua_pushnil(L);
is_nan_or_inf = 0;
}
}

return 2;
}

Expand Down

0 comments on commit 5366e0c

Please sign in to comment.