Skip to content

Commit 005b8bf

Browse files
committed
pkey: PEM password callback
1 parent 4f41ae9 commit 005b8bf

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

src/openssl.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4062,10 +4062,32 @@ static BIO *getbio(lua_State *L) {
40624062
} /* getbio() */
40634063

40644064

4065+
/*
4066+
* PEM password callback for openssl
4067+
*
4068+
* Expects nil, string, or function on top of the stack. Errors from the
4069+
* user-provided function are not reported. Leaves one item on the top of the
4070+
* stack: nil, the original string, or the return value.
4071+
*
4072+
* This callback may be called twice by pk_new when the PEM key type is not
4073+
* specified. The user-provided function is called only once because it gets
4074+
* replaced by the return value.
4075+
*/
40654076
static int pem_pw_cb(char *buf, int size, int rwflag, void *u) {
4066-
if (!u)
4077+
lua_State *L = (lua_State *) u;
4078+
4079+
if (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0)) {
4080+
lua_pop(L, 1);
4081+
lua_pushnil(L);
4082+
}
4083+
4084+
if (lua_isnil(L, -1))
40674085
return 0;
4068-
char *pass = (char *) u;
4086+
4087+
const char *pass = lua_tostring(L, -1);
4088+
if (!pass)
4089+
return 0;
4090+
40694091
strncpy(buf, pass, size);
40704092
return MIN(strlen(pass), (unsigned int) size);
40714093
} /* pem_pw_cb() */
@@ -4310,7 +4332,7 @@ static int pk_new(lua_State *L) {
43104332
} else if (lua_isstring(L, 1)) {
43114333
int format;
43124334
int pubonly = 0, prvtonly = 0;
4313-
const char *type, *data, *pass;
4335+
const char *type, *data;
43144336
size_t len;
43154337
BIO *bio;
43164338
EVP_PKEY *pub = NULL, *prvt = NULL;
@@ -4341,8 +4363,7 @@ static int pk_new(lua_State *L) {
43414363
}
43424364
}
43434365

4344-
pass = luaL_optstring(L, 4, NULL);
4345-
if (pass) {
4366+
if (!lua_isnil(L, 4)) {
43464367
if (format == X509_DER)
43474368
return luaL_error(L, "decryption supported only for PEM keys");
43484369
else format = X509_PEM;
@@ -4354,6 +4375,8 @@ static int pk_new(lua_State *L) {
43544375
return auxL_error(L, auxL_EOPENSSL, "pkey.new");
43554376

43564377
if (format == X509_PEM || format == X509_ANY) {
4378+
lua_pushvalue(L, 4);
4379+
43574380
if (!prvtonly && !pub) {
43584381
/*
43594382
* BIO_reset is a rewind for read-only
@@ -4362,16 +4385,18 @@ static int pk_new(lua_State *L) {
43624385
*/
43634386
BIO_reset(bio);
43644387

4365-
if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, pass)))
4388+
if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, L)))
43664389
goterr = 1;
43674390
}
43684391

43694392
if (!pubonly && !prvt) {
43704393
BIO_reset(bio);
43714394

4372-
if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, pass)))
4395+
if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, L)))
43734396
goterr = 1;
43744397
}
4398+
4399+
lua_pop(L, 1);
43754400
}
43764401

43774402
if (format == X509_DER || format == X509_ANY) {
@@ -4712,7 +4737,6 @@ static int pk_toPEM(lua_State *L) {
47124737
int type;
47134738
const char *cname = NULL;
47144739
const EVP_CIPHER *cipher = NULL;
4715-
const char *pass = NULL;
47164740

47174741
if (lua_istable(L, i)) {
47184742
loadfield(L, i, "cipher", LUA_TSTRING, &cname);
@@ -4739,13 +4763,17 @@ static int pk_toPEM(lua_State *L) {
47394763
cipher = EVP_get_cipherbyname(cname);
47404764
if (!cipher)
47414765
return luaL_error(L, "pkey:toPEM: unknown cipher: %s", cname);
4742-
if (!loadfield(L, i, "password", LUA_TSTRING, &pass))
4766+
if (!getfield(L, i, "password"))
47434767
return luaL_error(L, "pkey:toPEM: password not defined");
47444768
}
4769+
else
4770+
lua_pushnil(L);
47454771

4746-
if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, pass))
4772+
if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, L))
47474773
return auxL_error(L, auxL_EOPENSSL, "pkey:__tostring");
47484774

4775+
lua_pop(L, 1);
4776+
47494777
len = BIO_get_mem_data(bio, &pem);
47504778
lua_pushlstring(L, pem, len);
47514779
BIO_reset(bio);

0 commit comments

Comments
 (0)