From cf6557954e012cb9f4453d84566bec30958c5a58 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Thu, 3 May 2018 21:37:30 +0300 Subject: [PATCH 10/10] pkey: PEM password callback --- src/openssl.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/openssl.c b/src/openssl.c index 3af285b..03c2b68 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -4071,9 +4071,21 @@ static BIO *getbio(lua_State *L) { static int pem_pw_cb(char *buf, int size, int rwflag, void *u) { - if (!u) + lua_State *L = (lua_State *) u; + + if (lua_isnil(L, -1)) return 0; - char *pass = (char *) u; + + if (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0)) { + lua_pop(L, 1); + lua_pushnil(L); + return 0; + } + + const char *pass = lua_tostring(L, -1); + if (!pass) + return 0; + strncpy(buf, pass, size); return MIN(strlen(pass), (unsigned int) size); } /* pem_pw_cb() */ @@ -4318,7 +4330,7 @@ static int pk_new(lua_State *L) { } else if (lua_isstring(L, 1)) { int format; int pubonly = 0, prvtonly = 0; - const char *type, *data, *pass; + const char *type, *data; size_t len; BIO *bio; EVP_PKEY *pub = NULL, *prvt = NULL; @@ -4344,8 +4356,7 @@ static int pk_new(lua_State *L) { } } - pass = luaL_optstring(L, -1, NULL); - if (pass) { + if (!lua_isnil(L, -1)) { if (format == X509_DER) return luaL_error(L, "decryption supported only for PEM keys"); else format = X509_PEM; @@ -4359,6 +4370,8 @@ static int pk_new(lua_State *L) { return auxL_error(L, auxL_EOPENSSL, "pkey.new"); if (format == X509_PEM || format == X509_ANY) { + lua_pushvalue(L, -2); + if (!prvtonly && !pub) { /* * BIO_reset is a rewind for read-only @@ -4367,16 +4380,18 @@ static int pk_new(lua_State *L) { */ BIO_reset(bio); - if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, pass))) + if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, L))) goterr = 1; } if (!pubonly && !prvt) { BIO_reset(bio); - if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, pass))) + if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, L))) goterr = 1; } + + lua_pop(L, 1); } if (format == X509_DER || format == X509_ANY) { @@ -4717,7 +4732,6 @@ static int pk_toPEM(lua_State *L) { int type; const char *cname = NULL; const EVP_CIPHER *cipher = NULL; - const char *pass = NULL; if (lua_istable(L, i)) { loadfield(L, i, "cipher", LUA_TSTRING, &cname); @@ -4744,13 +4758,16 @@ static int pk_toPEM(lua_State *L) { cipher = EVP_get_cipherbyname(cname); if (!cipher) return luaL_error(L, "pkey:toPEM: unknown cipher: %s", cname); - if (!loadfield(L, i, "password", LUA_TSTRING, &pass)) + if (!getfield(L, i, "password")) return luaL_error(L, "pkey:toPEM: password not defined"); } - if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, pass)) + if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, L)) return auxL_error(L, auxL_EOPENSSL, "pkey:__tostring"); + if (cname) + lua_pop(L, 1); + len = BIO_get_mem_data(bio, &pem); lua_pushlstring(L, pem, len); BIO_reset(bio); -- 2.24.1