From f5ceb7d11ffd98baa5fe06756370b60f2379195b Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Sun, 3 Jan 2016 08:12:54 +1100
Subject: bignum.new: Allow initialisation from hex strings

---
 src/openssl.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 71aaed4..82f3298 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1673,7 +1673,7 @@ static _Bool f2bn(BIGNUM **bn, double f) {
 
 static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 	BIGNUM **bn;
-	const char *dec;
+	const char *str;
 	size_t len;
 
 	index = lua_absindex(L, index);
@@ -1682,14 +1682,19 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 	case LUA_TSTRING:
 		*lvalue = 0;
 
-		dec = lua_tolstring(L, index, &len);
+		str = lua_tolstring(L, index, &len);
 
-		luaL_argcheck(L, len > 0 && *dec, index, "invalid big number string");
+		luaL_argcheck(L, len > 0 && *str, index, "invalid big number string");
 
 		bn = prepsimple(L, BIGNUM_CLASS);
 
-		if (!BN_dec2bn(bn, dec))
-			auxL_error(L, auxL_EOPENSSL, "bignum");
+		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
+			if (!BN_hex2bn(bn, str+2))
+				auxL_error(L, auxL_EOPENSSL, "bignum");
+		} else {
+			if (!BN_dec2bn(bn, str))
+				auxL_error(L, auxL_EOPENSSL, "bignum");
+		}
 
 		lua_replace(L, index);
 
-- 
cgit v1.2.3-55-g6feb


From ae3506413067af8d209d16ffc10c2e7c99dc6bba Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Sun, 3 Jan 2016 08:14:17 +1100
Subject: bignum: Add fromBinary constructor

Closes #44
---
 src/openssl.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/openssl.c b/src/openssl.c
index 82f3298..0a444c8 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1598,6 +1598,17 @@ static int bn_new(lua_State *L) {
 } /* bn_new() */
 
 
+static int bn_fromBinary(lua_State *L) {
+	size_t len;
+	const char *s = luaL_checklstring(L, 1, &len);
+	BIGNUM *bn = bn_push(L);
+	if (!BN_bin2bn((const unsigned char*)s, len, bn)) {
+		auxL_error(L, auxL_EOPENSSL, "bignum");
+	}
+	return 1;
+} /* bn_fromBinary() */
+
+
 static int bn_interpose(lua_State *L) {
 	return interpose(L, BIGNUM_CLASS);
 } /* bn_interpose() */
@@ -2119,6 +2130,7 @@ static const luaL_Reg bn_metatable[] = {
 static const luaL_Reg bn_globals[] = {
 	{ "new",           &bn_new },
 	{ "interpose",     &bn_interpose },
+	{ "fromBinary",    &bn_fromBinary },
 	{ "generatePrime", &bn_generatePrime },
 	{ NULL,            NULL },
 };
-- 
cgit v1.2.3-55-g6feb


From 5dec5e287e60d13008373a38eadce91cf02da6a0 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Sun, 3 Jan 2016 10:42:26 +1100
Subject: bignum: handle negative hex numbers

---
 src/openssl.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 0a444c8..66a6168 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1686,6 +1686,7 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 	BIGNUM **bn;
 	const char *str;
 	size_t len;
+	_Bool neg, hex = 0;
 
 	index = lua_absindex(L, index);
 
@@ -1697,11 +1698,19 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 
 		luaL_argcheck(L, len > 0 && *str, index, "invalid big number string");
 
+		neg = (str[0] == '-');
+
+		if (str[neg] == '0' && (str[neg+1] == 'x' || str[neg+1] == 'X')) {
+			hex = 1;
+		}
+
 		bn = prepsimple(L, BIGNUM_CLASS);
 
-		if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
-			if (!BN_hex2bn(bn, str+2))
+		if (hex) {
+			if (!BN_hex2bn(bn, str+2+neg))
 				auxL_error(L, auxL_EOPENSSL, "bignum");
+			if (neg)
+				BN_set_negative(*bn, 1);
 		} else {
 			if (!BN_dec2bn(bn, str))
 				auxL_error(L, auxL_EOPENSSL, "bignum");
-- 
cgit v1.2.3-55-g6feb


From 59cc755e2a48b0d479480c09bf0b9893ffdfce36 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Sun, 3 Jan 2016 10:43:16 +1100
Subject: bignum: validate hex and decimal strings before feeding to openssl

OpenSSL doesn't throw an error on invalid numbers
---
 src/openssl.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 66a6168..4ca8da7 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -29,7 +29,7 @@
 #include <strings.h>      /* strcasecmp(3) */
 #include <math.h>         /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */
 #include <time.h>         /* struct tm time_t strptime(3) time(2) */
-#include <ctype.h>        /* tolower(3) */
+#include <ctype.h>        /* isdigit(3), isxdigit(3), tolower(3) */
 #include <errno.h>        /* ENOMEM ENOTSUP EOVERFLOW errno */
 #include <assert.h>       /* assert */
 
@@ -1685,7 +1685,7 @@ static _Bool f2bn(BIGNUM **bn, double f) {
 static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 	BIGNUM **bn;
 	const char *str;
-	size_t len;
+	size_t len, i;
 	_Bool neg, hex = 0;
 
 	index = lua_absindex(L, index);
@@ -1702,6 +1702,15 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 
 		if (str[neg] == '0' && (str[neg+1] == 'x' || str[neg+1] == 'X')) {
 			hex = 1;
+			for (i = 2+neg; i < len; i++) {
+				if (!isxdigit(str[i]))
+					luaL_argerror(L, 1, "invalid hex string");
+			}
+		} else {
+			for (i = neg; i < len; i++) {
+				if (!isdigit(str[i]))
+					luaL_argerror(L, 1, "invalid decimal string");
+			}
 		}
 
 		bn = prepsimple(L, BIGNUM_CLASS);
-- 
cgit v1.2.3-55-g6feb


From f53625badddd6c75421e5d5132c4eac6ee6eb01d Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Sun, 3 Jan 2016 10:55:28 +1100
Subject: bignum: Don't allow empty numbers/strings to pass

Previously, "-" would pass the len>0 check; and end up as "0"
The `*str` check was redundant, the switch/case already ensures the object at the given stack index is a string
---
 src/openssl.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index 4ca8da7..dba7c75 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1686,7 +1686,7 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 	BIGNUM **bn;
 	const char *str;
 	size_t len, i;
-	_Bool neg, hex = 0;
+	_Bool neg, hex;
 
 	index = lua_absindex(L, index);
 
@@ -1696,17 +1696,17 @@ static BIGNUM *(checkbig)(lua_State *L, int index, _Bool *lvalue) {
 
 		str = lua_tolstring(L, index, &len);
 
-		luaL_argcheck(L, len > 0 && *str, index, "invalid big number string");
-
 		neg = (str[0] == '-');
+		hex = (str[neg] == '0' && (str[neg+1] == 'x' || str[neg+1] == 'X'));
 
-		if (str[neg] == '0' && (str[neg+1] == 'x' || str[neg+1] == 'X')) {
-			hex = 1;
+		if (hex) {
+			luaL_argcheck(L, len > 2+(size_t)neg, index, "invalid hex string");
 			for (i = 2+neg; i < len; i++) {
 				if (!isxdigit(str[i]))
 					luaL_argerror(L, 1, "invalid hex string");
 			}
 		} else {
+			luaL_argcheck(L, len > neg, index, "invalid decimal string");
 			for (i = neg; i < len; i++) {
 				if (!isdigit(str[i]))
 					luaL_argerror(L, 1, "invalid decimal string");
-- 
cgit v1.2.3-55-g6feb