From f5ceb7d11ffd98baa5fe06756370b60f2379195b Mon Sep 17 00:00:00 2001 From: daurnimator 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-59-g8ed1b From ae3506413067af8d209d16ffc10c2e7c99dc6bba Mon Sep 17 00:00:00 2001 From: daurnimator 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-59-g8ed1b From 5dec5e287e60d13008373a38eadce91cf02da6a0 Mon Sep 17 00:00:00 2001 From: daurnimator 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-59-g8ed1b From 59cc755e2a48b0d479480c09bf0b9893ffdfce36 Mon Sep 17 00:00:00 2001 From: daurnimator 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 /* strcasecmp(3) */ #include /* INFINITY fabs(3) floor(3) frexp(3) fmod(3) round(3) isfinite(3) */ #include /* struct tm time_t strptime(3) time(2) */ -#include /* tolower(3) */ +#include /* isdigit(3), isxdigit(3), tolower(3) */ #include /* ENOMEM ENOTSUP EOVERFLOW errno */ #include /* 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-59-g8ed1b From f53625badddd6c75421e5d5132c4eac6ee6eb01d Mon Sep 17 00:00:00 2001 From: daurnimator 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-59-g8ed1b