aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/openssl.c260
1 files changed, 258 insertions, 2 deletions
diff --git a/src/openssl.c b/src/openssl.c
index 01bf2c8..84a0155 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");
+
+ return *ud;
+} /* bn_dup() */
+
+
#define checkbig_(a, b, c, ...) checkbig((a), (b), (c))
#define checkbig(...) checkbig_(__VA_ARGS__, &(_Bool){ 0 }, 0)
@@ -2151,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);
@@ -2478,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);
@@ -2498,6 +2508,251 @@ static int pk_toPEM(lua_State *L) {
} /* pk_toPEM() */
+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, key.rsa->n);
+
+ break;
+ case PK_RSA_E:
+ /* RSA public exponent e */
+ bn_dup(L, key.rsa->e);
+
+ break;
+ case PK_RSA_D:
+ /* RSA secret exponent d */
+ bn_dup(L, key.rsa->d);
+
+ break;
+ case PK_RSA_P:
+ /* RSA secret prime p */
+ bn_dup(L, key.rsa->p);
+
+ break;
+ case PK_RSA_Q:
+ /* RSA secret prime q with p < q */
+ bn_dup(L, key.rsa->q);
+
+ break;
+ case PK_RSA_DMP1:
+ /* exponent1 */
+ bn_dup(L, key.rsa->dmp1);
+
+ break;
+ case PK_RSA_DMQ1:
+ /* exponent2 */
+ bn_dup(L, key.rsa->dmq1);
+
+ break;
+ case PK_RSA_IQMP:
+ /* coefficient */
+ bn_dup(L, key.rsa->iqmp);
+
+ break;
+ case PK_DSA_P:
+ bn_dup(L, key.dsa->p);
+
+ break;
+ case PK_DSA_Q:
+ bn_dup(L, key.dsa->q);
+
+ break;
+ case PK_DSA_G:
+ bn_dup(L, key.dsa->g);
+
+ break;
+ case PK_DSA_PUB_KEY:
+ bn_dup(L, key.dsa->pub_key);
+
+ break;
+ case PK_DSA_PRIV_KEY:
+ bn_dup(L, key.dsa->priv_key);
+
+ break;
+ 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;
+
+ 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(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), "");
+
+ break;
+ case EVP_PKEY_DSA:
+ optlist = pk_dsa_optlist;
+ luaL_checkstack(L, countof(pk_dsa_optlist), "");
+
+ break;
+ case EVP_PKEY_DH:
+ optlist = pk_dh_optlist;
+ luaL_checkstack(L, countof(pk_dh_optlist), "");
+
+ 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);
+ }
+ }
+
+ 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() */
+
+
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);
@@ -2543,6 +2798,7 @@ static const luaL_Reg pk_methods[] = {
{ "sign", &pk_sign },
{ "verify", &pk_verify },
{ "toPEM", &pk_toPEM },
+ { "getParameters", &pk_getParameters },
{ NULL, NULL },
};