From bda7ea7cdc0a5a76a5ed2ed5979d101930918696 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 7 Dec 2015 00:06:02 +1100
Subject: Add 'pkey:getParameters()' function that returns private key
 parameters as a table of bignums

---
 src/openssl.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/src/openssl.c b/src/openssl.c
index 9dbcda7..e05fcc4 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -2458,6 +2458,104 @@ static int pk_toPEM(lua_State *L) {
 } /* pk_toPEM() */
 
 
+static int pk_getParameters(lua_State *L) {
+	EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS);
+	void *tmp;
+	const EC_GROUP *group;
+	const EC_POINT *public_key;
+
+	if (!(tmp = EVP_PKEY_get0(key)))
+		return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+
+	lua_newtable(L);
+
+	switch (EVP_PKEY_base_id(key)) {
+	case EVP_PKEY_RSA:
+		/* RSA public modulus n */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->n))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "n");
+
+		/* RSA public exponent e */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->e))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "e");
+
+		/* RSA secret exponent d */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->d))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "d");
+
+		/* RSA secret prime p */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->p))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "p");
+
+		/* RSA secret prime q with p < q */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->q))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "q");
+
+		/* exponent1 */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->dmp1))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "dmp1");
+
+		/* exponent2 */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->dmq1))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "dmq1");
+
+		/* coefficient */
+		if (!BN_copy(bn_push(L), ((RSA*)tmp)->iqmp))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "iqmp");
+
+		break;
+	case EVP_PKEY_DH:
+		/* prime */
+		if (!BN_copy(bn_push(L), ((DH*)tmp)->p))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "p");
+
+		/* generator */
+		if (!BN_copy(bn_push(L), ((DH*)tmp)->g))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "g");
+
+		/* pub_key */
+		if (!BN_copy(bn_push(L), ((DH*)tmp)->pub_key))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "pub_key");
+
+		/* priv_key */
+		if (!BN_copy(bn_push(L), ((DH*)tmp)->priv_key))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "priv_key");
+
+		break;
+	case EVP_PKEY_EC:
+		/* pub_key */
+		if (!(group = EC_KEY_get0_group(tmp)) || !(public_key = EC_KEY_get0_public_key(tmp)))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		if (!BN_copy(bn_push(L), EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(tmp), NULL, getctx(L))))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "pub_key");
+
+		/* priv_key */
+		if (!BN_copy(bn_push(L), EC_KEY_get0_private_key(tmp)))
+			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
+		lua_setfield(L, -2, "priv_key");
+
+		break;
+	default:
+		return luaL_error(L, "%d: unsupported EVP base type", EVP_PKEY_base_id(key));
+	} /* switch() */
+
+	return 1;
+}
+
+
 static int pk__tostring(lua_State *L) {
 	EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS);
 	int type = optencoding(L, 2, "pem", X509_PEM|X509_DER);
@@ -2503,6 +2601,7 @@ static const luaL_Reg pk_methods[] = {
 	{ "sign",          &pk_sign },
 	{ "verify",        &pk_verify },
 	{ "toPEM",         &pk_toPEM },
+	{ "getParameters", &pk_getParameters },
 	{ NULL,            NULL },
 };
 
-- 
cgit v1.2.3-59-g8ed1b


From ecff1f7b08466cc1d1c28f009f0e483fa4ab2a8e Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Mon, 7 Dec 2015 01:34:59 +1100
Subject: Add bn_dup function to make sure BN_FLG_SECURE is kept in copies

---
 src/openssl.c | 38 ++++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/openssl.c b/src/openssl.c
index e05fcc4..41262c5 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1558,6 +1558,16 @@ static BIGNUM *bn_push(lua_State *L) {
 } /* bn_push() */
 
 
+static BIGNUM *bn_dup(lua_State *L, const BIGNUM *src) {
+	BIGNUM **ud = prepsimple(L, BIGNUM_CLASS);
+
+	if (!(*ud = BN_dup(src)))
+		auxL_error(L, auxL_EOPENSSL, "bignum.new");
+
+	return *ud;
+} /* bn_dup() */
+
+
 #define checkbig_(a, b, c, ...) checkbig((a), (b), (c))
 #define checkbig(...) checkbig_(__VA_ARGS__, &(_Bool){ 0 }, 0)
 
@@ -2472,64 +2482,64 @@ static int pk_getParameters(lua_State *L) {
 	switch (EVP_PKEY_base_id(key)) {
 	case EVP_PKEY_RSA:
 		/* RSA public modulus n */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->n))
+		if (!bn_dup(L, ((RSA*)tmp)->n))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "n");
 
 		/* RSA public exponent e */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->e))
+		if (!bn_dup(L, ((RSA*)tmp)->e))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "e");
 
 		/* RSA secret exponent d */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->d))
+		if (!bn_dup(L, ((RSA*)tmp)->d))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "d");
 
 		/* RSA secret prime p */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->p))
+		if (!bn_dup(L, ((RSA*)tmp)->p))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "p");
 
 		/* RSA secret prime q with p < q */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->q))
+		if (!bn_dup(L, ((RSA*)tmp)->q))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "q");
 
 		/* exponent1 */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->dmp1))
+		if (!bn_dup(L, ((RSA*)tmp)->dmp1))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "dmp1");
 
 		/* exponent2 */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->dmq1))
+		if (!bn_dup(L, ((RSA*)tmp)->dmq1))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "dmq1");
 
 		/* coefficient */
-		if (!BN_copy(bn_push(L), ((RSA*)tmp)->iqmp))
+		if (!bn_dup(L, ((RSA*)tmp)->iqmp))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "iqmp");
 
 		break;
 	case EVP_PKEY_DH:
 		/* prime */
-		if (!BN_copy(bn_push(L), ((DH*)tmp)->p))
+		if (!bn_dup(L, ((DH*)tmp)->p))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "p");
 
 		/* generator */
-		if (!BN_copy(bn_push(L), ((DH*)tmp)->g))
+		if (!bn_dup(L, ((DH*)tmp)->g))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "g");
 
 		/* pub_key */
-		if (!BN_copy(bn_push(L), ((DH*)tmp)->pub_key))
+		if (!bn_dup(L, ((DH*)tmp)->pub_key))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "pub_key");
 
 		/* priv_key */
-		if (!BN_copy(bn_push(L), ((DH*)tmp)->priv_key))
+		if (!bn_dup(L, ((DH*)tmp)->priv_key))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "priv_key");
 
@@ -2538,12 +2548,12 @@ static int pk_getParameters(lua_State *L) {
 		/* pub_key */
 		if (!(group = EC_KEY_get0_group(tmp)) || !(public_key = EC_KEY_get0_public_key(tmp)))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
-		if (!BN_copy(bn_push(L), EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(tmp), NULL, getctx(L))))
+		if (!bn_dup(L, EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(tmp), NULL, getctx(L))))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "pub_key");
 
 		/* priv_key */
-		if (!BN_copy(bn_push(L), EC_KEY_get0_private_key(tmp)))
+		if (!bn_dup(L, EC_KEY_get0_private_key(tmp)))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "priv_key");
 
-- 
cgit v1.2.3-59-g8ed1b


From fcd7076005e7e81e37e31df9e5b712214cead2c6 Mon Sep 17 00:00:00 2001
From: daurnimator <quae@daurnimator.com>
Date: Thu, 10 Dec 2015 23:11:35 +1100
Subject: pk_getParameters: Add 'public_only' flag to only export the public
 key parameters

Should possibly a string/table instead?
---
 src/openssl.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/openssl.c b/src/openssl.c
index 41262c5..82483af 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -2470,6 +2470,8 @@ static int pk_toPEM(lua_State *L) {
 
 static int pk_getParameters(lua_State *L) {
 	EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS);
+	_Bool public_only = lua_toboolean(L, 2);
+
 	void *tmp;
 	const EC_GROUP *group;
 	const EC_POINT *public_key;
@@ -2491,6 +2493,8 @@ static int pk_getParameters(lua_State *L) {
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "e");
 
+		if (public_only) break;
+
 		/* RSA secret exponent d */
 		if (!bn_dup(L, ((RSA*)tmp)->d))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
@@ -2538,6 +2542,8 @@ static int pk_getParameters(lua_State *L) {
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "pub_key");
 
+		if (public_only) break;
+
 		/* priv_key */
 		if (!bn_dup(L, ((DH*)tmp)->priv_key))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
@@ -2552,6 +2558,8 @@ static int pk_getParameters(lua_State *L) {
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
 		lua_setfield(L, -2, "pub_key");
 
+		if (public_only) break;
+
 		/* priv_key */
 		if (!bn_dup(L, EC_KEY_get0_private_key(tmp)))
 			return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters");
-- 
cgit v1.2.3-59-g8ed1b