From bda7ea7cdc0a5a76a5ed2ed5979d101930918696 Mon Sep 17 00:00:00 2001 From: daurnimator 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 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 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 From b105f09ccc6ef4a90b97745f50a46a5910edcdc1 Mon Sep 17 00:00:00 2001 From: William Ahern Date: Fri, 18 Dec 2015 14:08:28 +0800 Subject: put EC variable declarations inside OPENSSL_NO_EC preprocessor guard (unable to confirm which, if any, of our platforms still don't support EC natively --- src/openssl.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/openssl.c b/src/openssl.c index c3f8bbb..dea175e 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -2511,10 +2511,7 @@ 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; if (!(tmp = EVP_PKEY_get0(key))) return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); @@ -2590,7 +2587,11 @@ static int pk_getParameters(lua_State *L) { lua_setfield(L, -2, "priv_key"); break; - case EVP_PKEY_EC: +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: { + const EC_GROUP *group; + const EC_POINT *public_key; + /* 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"); @@ -2606,12 +2607,14 @@ static int pk_getParameters(lua_State *L) { lua_setfield(L, -2, "priv_key"); break; + } +#endif default: return luaL_error(L, "%d: unsupported EVP base type", EVP_PKEY_base_id(key)); } /* switch() */ return 1; -} +} /* pk_getParameters() */ static int pk__tostring(lua_State *L) { -- cgit v1.2.3-59-g8ed1b From 73b1a614759da1bc064d3b6cfff221981b04d8b8 Mon Sep 17 00:00:00 2001 From: William Ahern Date: Fri, 18 Dec 2015 14:14:53 +0800 Subject: bn_dup only returns on success, so remove error handling from bn_dup calls --- src/openssl.c | 60 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/openssl.c b/src/openssl.c index dea175e..5bc42ab 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -1562,7 +1562,7 @@ 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"); + auxL_error(L, auxL_EOPENSSL, "bignum"); return *ud; } /* bn_dup() */ @@ -2514,76 +2514,66 @@ static int pk_getParameters(lua_State *L) { void *tmp; if (!(tmp = EVP_PKEY_get0(key))) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + goto sslerr; lua_newtable(L); switch (EVP_PKEY_base_id(key)) { case EVP_PKEY_RSA: /* RSA public modulus n */ - if (!bn_dup(L, ((RSA*)tmp)->n)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->n); lua_setfield(L, -2, "n"); /* RSA public exponent e */ - if (!bn_dup(L, ((RSA*)tmp)->e)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->e); lua_setfield(L, -2, "e"); - if (public_only) break; + if (public_only) + break; /* RSA secret exponent d */ - if (!bn_dup(L, ((RSA*)tmp)->d)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->d); lua_setfield(L, -2, "d"); /* RSA secret prime p */ - if (!bn_dup(L, ((RSA*)tmp)->p)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->p); lua_setfield(L, -2, "p"); /* RSA secret prime q with p < q */ - if (!bn_dup(L, ((RSA*)tmp)->q)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->q); lua_setfield(L, -2, "q"); /* exponent1 */ - if (!bn_dup(L, ((RSA*)tmp)->dmp1)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->dmp1); lua_setfield(L, -2, "dmp1"); /* exponent2 */ - if (!bn_dup(L, ((RSA*)tmp)->dmq1)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->dmq1); lua_setfield(L, -2, "dmq1"); /* coefficient */ - if (!bn_dup(L, ((RSA*)tmp)->iqmp)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((RSA*)tmp)->iqmp); lua_setfield(L, -2, "iqmp"); break; case EVP_PKEY_DH: /* prime */ - if (!bn_dup(L, ((DH*)tmp)->p)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((DH*)tmp)->p); lua_setfield(L, -2, "p"); /* generator */ - if (!bn_dup(L, ((DH*)tmp)->g)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((DH*)tmp)->g); lua_setfield(L, -2, "g"); /* pub_key */ - if (!bn_dup(L, ((DH*)tmp)->pub_key)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((DH*)tmp)->pub_key); lua_setfield(L, -2, "pub_key"); - if (public_only) break; + if (public_only) + break; /* priv_key */ - if (!bn_dup(L, ((DH*)tmp)->priv_key)) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, ((DH*)tmp)->priv_key); lua_setfield(L, -2, "priv_key"); break; @@ -2594,16 +2584,16 @@ 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_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"); + goto sslerr; + bn_dup(L, EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(tmp), NULL, getctx(L))); lua_setfield(L, -2, "pub_key"); - if (public_only) break; + if (public_only) + break; /* priv_key */ - if (!bn_dup(L, EC_KEY_get0_private_key(tmp))) - return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + bn_dup(L, EC_KEY_get0_private_key(tmp)); + goto sslerr; lua_setfield(L, -2, "priv_key"); break; @@ -2614,6 +2604,8 @@ static int pk_getParameters(lua_State *L) { } /* switch() */ return 1; +sslerr: + return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); } /* pk_getParameters() */ -- cgit v1.2.3-59-g8ed1b From 7d6ee936398acc1846671fd9c94ecfacfd953c82 Mon Sep 17 00:00:00 2001 From: William Ahern Date: Fri, 18 Dec 2015 16:02:25 +0800 Subject: return value list instead of table if parameter names specified explicitly --- src/openssl.c | 272 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 208 insertions(+), 64 deletions(-) diff --git a/src/openssl.c b/src/openssl.c index 5bc42ab..84a0155 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -2161,7 +2161,7 @@ creat: } #endif default: - return luaL_error(L, "%d: unknown EVP base type (%d)", EVP_PKEY_type(type), type); + return luaL_error(L, "%d: unsupported EVP_PKEY base type", EVP_PKEY_type(type)); } /* switch() */ } else if (lua_isstring(L, 1)) { int type = optencoding(L, 2, "*", X509_ANY|X509_PEM|X509_DER); @@ -2488,7 +2488,7 @@ static int pk_toPEM(lua_State *L) { } #endif default: - return luaL_error(L, "%d: unknown EVP base type", EVP_PKEY_type(key->type)); + return luaL_error(L, "%d: unsupported EVP_PKEY base type", EVP_PKEY_type(key->type)); } lua_pushlstring(L, pem, len); @@ -2508,102 +2508,246 @@ static int pk_toPEM(lua_State *L) { } /* pk_toPEM() */ -static int pk_getParameters(lua_State *L) { - EVP_PKEY *key = checksimple(L, 1, PKEY_CLASS); - _Bool public_only = lua_toboolean(L, 2); - void *tmp; - - if (!(tmp = EVP_PKEY_get0(key))) - goto sslerr; - - lua_newtable(L); - - switch (EVP_PKEY_base_id(key)) { +enum pk_param { +#define PK_RSA_OPTLIST { "n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp", NULL } +#define PK_RSA_OPTOFFSET PK_RSA_N + PK_RSA_N = 1, + PK_RSA_E, + PK_RSA_D, + PK_RSA_P, + PK_RSA_Q, + PK_RSA_DMP1, + PK_RSA_DMQ1, + PK_RSA_IQMP, + +#define PK_DSA_OPTLIST { "p", "q", "g", "pub_key", "priv_key", NULL } +#define PK_DSA_OPTOFFSET PK_DSA_P + PK_DSA_P, + PK_DSA_Q, + PK_DSA_G, + PK_DSA_PUB_KEY, + PK_DSA_PRIV_KEY, + +#define PK_DH_OPTLIST { "p", "g", "pub_key", "priv_key", NULL } +#define PK_DH_OPTOFFSET PK_DH_P + PK_DH_P, + PK_DH_G, + PK_DH_PUB_KEY, + PK_DH_PRIV_KEY, + +#define PK_EC_OPTLIST { "pub_key", "priv_key", NULL } +#define PK_EC_OPTOFFSET PK_EC_PUB_KEY + PK_EC_PUB_KEY, + PK_EC_PRIV_KEY, +}; /* enum pk_param */ + +static const char *const pk_rsa_optlist[] = PK_RSA_OPTLIST; +static const char *const pk_dsa_optlist[] = PK_DSA_OPTLIST; +static const char *const pk_dh_optlist[] = PK_DH_OPTLIST; +static const char *const pk_ec_optlist[] = PK_EC_OPTLIST; + +static int pk_checkparam(lua_State *L, int type, int index) { + switch (type) { case EVP_PKEY_RSA: + return luaL_checkoption(L, index, NULL, pk_rsa_optlist) + PK_RSA_OPTOFFSET; + case EVP_PKEY_DSA: + return luaL_checkoption(L, index, NULL, pk_dsa_optlist) + PK_DSA_OPTOFFSET; + case EVP_PKEY_DH: + return luaL_checkoption(L, index, NULL, pk_dh_optlist) + PK_DH_OPTOFFSET; + case EVP_PKEY_EC: + return luaL_checkoption(L, index, NULL, pk_ec_optlist) + PK_EC_OPTOFFSET; + default: + return luaL_error(L, "%d: unsupported EVP_PKEY base type", type); + } +} /* pk_checkparam() */ + +static void pk_pushparam(lua_State *L, void *_key, enum pk_param which) { + union { + RSA *rsa; + DH *dh; + DSA *dsa; + EC_KEY *ec; + } key = { _key }; + + switch (which) { + case PK_RSA_N: /* RSA public modulus n */ - bn_dup(L, ((RSA*)tmp)->n); - lua_setfield(L, -2, "n"); + bn_dup(L, key.rsa->n); + break; + case PK_RSA_E: /* RSA public exponent e */ - bn_dup(L, ((RSA*)tmp)->e); - lua_setfield(L, -2, "e"); - - if (public_only) - break; + bn_dup(L, key.rsa->e); + break; + case PK_RSA_D: /* RSA secret exponent d */ - bn_dup(L, ((RSA*)tmp)->d); - lua_setfield(L, -2, "d"); + bn_dup(L, key.rsa->d); + break; + case PK_RSA_P: /* RSA secret prime p */ - bn_dup(L, ((RSA*)tmp)->p); - lua_setfield(L, -2, "p"); + bn_dup(L, key.rsa->p); + break; + case PK_RSA_Q: /* RSA secret prime q with p < q */ - bn_dup(L, ((RSA*)tmp)->q); - lua_setfield(L, -2, "q"); + bn_dup(L, key.rsa->q); + break; + case PK_RSA_DMP1: /* exponent1 */ - bn_dup(L, ((RSA*)tmp)->dmp1); - lua_setfield(L, -2, "dmp1"); + bn_dup(L, key.rsa->dmp1); + break; + case PK_RSA_DMQ1: /* exponent2 */ - bn_dup(L, ((RSA*)tmp)->dmq1); - lua_setfield(L, -2, "dmq1"); + bn_dup(L, key.rsa->dmq1); + break; + case PK_RSA_IQMP: /* coefficient */ - bn_dup(L, ((RSA*)tmp)->iqmp); - lua_setfield(L, -2, "iqmp"); + bn_dup(L, key.rsa->iqmp); break; - case EVP_PKEY_DH: - /* prime */ - bn_dup(L, ((DH*)tmp)->p); - lua_setfield(L, -2, "p"); + case PK_DSA_P: + bn_dup(L, key.dsa->p); - /* generator */ - bn_dup(L, ((DH*)tmp)->g); - lua_setfield(L, -2, "g"); + break; + case PK_DSA_Q: + bn_dup(L, key.dsa->q); - /* pub_key */ - bn_dup(L, ((DH*)tmp)->pub_key); - lua_setfield(L, -2, "pub_key"); + break; + case PK_DSA_G: + bn_dup(L, key.dsa->g); - if (public_only) - break; + break; + case PK_DSA_PUB_KEY: + bn_dup(L, key.dsa->pub_key); - /* priv_key */ - bn_dup(L, ((DH*)tmp)->priv_key); - lua_setfield(L, -2, "priv_key"); + break; + case PK_DSA_PRIV_KEY: + bn_dup(L, key.dsa->priv_key); break; -#ifndef OPENSSL_NO_EC - case EVP_PKEY_EC: { + case PK_DH_P: + bn_dup(L, key.dh->p); + + break; + case PK_DH_G: + bn_dup(L, key.dh->g); + + break; + case PK_DH_PUB_KEY: + bn_dup(L, key.dh->pub_key); + + break; + case PK_DH_PRIV_KEY: + bn_dup(L, key.dh->priv_key); + + break; + case PK_EC_PUB_KEY: { const EC_GROUP *group; const EC_POINT *public_key; - /* pub_key */ - if (!(group = EC_KEY_get0_group(tmp)) || !(public_key = EC_KEY_get0_public_key(tmp))) + if (!(group = EC_KEY_get0_group(key.ec)) || !(public_key = EC_KEY_get0_public_key(key.ec))) goto sslerr; - bn_dup(L, EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(tmp), NULL, getctx(L))); - lua_setfield(L, -2, "pub_key"); + bn_dup(L, EC_POINT_point2bn(group, public_key, EC_KEY_get_conv_form(key.ec), NULL, getctx(L))); + + break; + } + case PK_EC_PRIV_KEY: + bn_dup(L, EC_KEY_get0_private_key(key.ec)); + + break; + default: + luaL_error(L, "%d: invalid EVP_PKEY parameter", which); + } + + return; +sslerr: + auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); + + return; +} /* pk_pushparam() */ + + +static int pk_getParameters(lua_State *L) { + EVP_PKEY *_key = checksimple(L, 1, PKEY_CLASS); + int type = EVP_PKEY_base_id(_key); + void *key; + int otop, index, tindex; + + if (!(key = EVP_PKEY_get0(_key))) + goto sslerr; + + if (lua_isnoneornil(L, 2)) { + const char *const *optlist; + const char *const *opt; + + switch (type) { + case EVP_PKEY_RSA: + optlist = pk_rsa_optlist; + luaL_checkstack(L, countof(pk_rsa_optlist), ""); - if (public_only) break; + case EVP_PKEY_DSA: + optlist = pk_dsa_optlist; + luaL_checkstack(L, countof(pk_dsa_optlist), ""); - /* priv_key */ - bn_dup(L, EC_KEY_get0_private_key(tmp)); - goto sslerr; - lua_setfield(L, -2, "priv_key"); + break; + case EVP_PKEY_DH: + optlist = pk_dh_optlist; + luaL_checkstack(L, countof(pk_dh_optlist), ""); - break; + break; + case EVP_PKEY_EC: + optlist = pk_ec_optlist; + luaL_checkstack(L, countof(pk_ec_optlist), ""); + + break; + default: + return luaL_error(L, "%d: unsupported EVP_PKEY base type", EVP_PKEY_base_id(key)); + } + + /* + * Use special "{" parameter to tell loop to push table. + * Subsequent parameters will be assigned as fields. + * + * NOTE: optlist arrays are NULL-terminated. luaL_checkstack() + * calls above left room for "{". + */ + lua_pushstring(L, "{"); + + for (opt = optlist; *opt; opt++) { + lua_pushstring(L, *opt); + } } -#endif - default: - return luaL_error(L, "%d: unsupported EVP base type", EVP_PKEY_base_id(key)); - } /* switch() */ - return 1; + otop = lua_gettop(L); + + /* provide space for results and working area */ + luaL_checkstack(L, (otop - 1) + LUA_MINSTACK, ""); + + /* no table index, yet */ + tindex = 0; + + for (index = 2; index <= otop; index++) { + const char *opt = luaL_checkstring(L, index); + + if (*opt == '{') { + lua_newtable(L); + tindex = lua_gettop(L); + } else { + pk_pushparam(L, key, pk_checkparam(L, type, index)); + + if (tindex) { + lua_setfield(L, tindex, opt); + } + } + } + + return lua_gettop(L) - otop; sslerr: return auxL_error(L, auxL_EOPENSSL, "pkey:getParameters"); } /* pk_getParameters() */ -- cgit v1.2.3-59-g8ed1b