Skip to content

Commit aeb4f95

Browse files
committed
pkey: PEM password callback
1 parent 66cb087 commit aeb4f95

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

src/openssl.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4105,10 +4105,28 @@ static BIO *getbio(lua_State *L) {
41054105
} /* getbio() */
41064106

41074107

4108+
/*
4109+
* PEM password callback for openssl
4110+
*
4111+
* Expects nil, string, or function on top of the stack. Leaves one item on the
4112+
* top of the stack: the original string, the string returned by the function,
4113+
* or nil (in case of an error or missing password).
4114+
*
4115+
* This callback may be called twice by pk_new when the PEM key is encrypted and
4116+
* its type is not specified. The user-provided function is called only once
4117+
* because it gets replaced on the stack by the return value. This callback may
4118+
* not be called at all if the supplied PEM key is not encrypted.
4119+
*/
41084120
static int pem_pw_cb(char *buf, int size, int rwflag, void *u) {
4109-
if (!u)
4121+
lua_State *L = (lua_State *) u;
4122+
4123+
if (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0) || !lua_isstring(L, -1)) {
4124+
lua_pop(L, 1);
4125+
lua_pushnil(L);
41104126
return -1;
4111-
char *pass = (char *) u;
4127+
}
4128+
4129+
const char *pass = lua_tostring(L, -1);
41124130
strncpy(buf, pass, size);
41134131
return MIN(strlen(pass), (unsigned int) size);
41144132
} /* pem_pw_cb() */
@@ -4353,7 +4371,7 @@ static int pk_new(lua_State *L) {
43534371
} else if (lua_isstring(L, 1)) {
43544372
int format;
43554373
int pubonly = 0, prvtonly = 0;
4356-
const char *type, *data, *pass;
4374+
const char *type, *data;
43574375
size_t len;
43584376
BIO *bio;
43594377
EVP_PKEY *pub = NULL, *prvt = NULL;
@@ -4384,8 +4402,7 @@ static int pk_new(lua_State *L) {
43844402
}
43854403
}
43864404

4387-
pass = luaL_optstring(L, 4, NULL);
4388-
if (pass) {
4405+
if (!lua_isnil(L, 4)) {
43894406
if (format == X509_DER)
43904407
return luaL_error(L, "decryption supported only for PEM keys");
43914408
else format = X509_PEM;
@@ -4397,6 +4414,8 @@ static int pk_new(lua_State *L) {
43974414
return auxL_error(L, auxL_EOPENSSL, "pkey.new");
43984415

43994416
if (format == X509_PEM || format == X509_ANY) {
4417+
lua_pushvalue(L, 4);
4418+
44004419
if (!prvtonly && !pub) {
44014420
/*
44024421
* BIO_reset is a rewind for read-only
@@ -4405,16 +4424,18 @@ static int pk_new(lua_State *L) {
44054424
*/
44064425
BIO_reset(bio);
44074426

4408-
if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, pass)))
4427+
if (!(pub = PEM_read_bio_PUBKEY(bio, NULL, pem_pw_cb, L)))
44094428
goterr = 1;
44104429
}
44114430

44124431
if (!pubonly && !prvt) {
44134432
BIO_reset(bio);
44144433

4415-
if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, pass)))
4434+
if (!(prvt = PEM_read_bio_PrivateKey(bio, NULL, pem_pw_cb, L)))
44164435
goterr = 1;
44174436
}
4437+
4438+
lua_pop(L, 1);
44184439
}
44194440

44204441
if (format == X509_DER || format == X509_ANY) {
@@ -4755,7 +4776,6 @@ static int pk_toPEM(lua_State *L) {
47554776
int type;
47564777
const char *cname = NULL;
47574778
const EVP_CIPHER *cipher = NULL;
4758-
const char *pass = NULL;
47594779

47604780
if (lua_istable(L, i)) {
47614781
loadfield(L, i, "cipher", LUA_TSTRING, &cname);
@@ -4782,13 +4802,17 @@ static int pk_toPEM(lua_State *L) {
47824802
cipher = EVP_get_cipherbyname(cname);
47834803
if (!cipher)
47844804
return luaL_error(L, "pkey:toPEM: unknown cipher: %s", cname);
4785-
if (!loadfield(L, i, "password", LUA_TSTRING, &pass))
4805+
if (!getfield(L, i, "password"))
47864806
return luaL_error(L, "pkey:toPEM: password not defined");
47874807
}
4808+
else
4809+
lua_pushnil(L);
47884810

4789-
if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, pass))
4811+
if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, L))
47904812
return auxL_error(L, auxL_EOPENSSL, "pkey:__tostring");
47914813

4814+
lua_pop(L, 1);
4815+
47924816
len = BIO_get_mem_data(bio, &pem);
47934817
lua_pushlstring(L, pem, len);
47944818
BIO_reset(bio);

0 commit comments

Comments
 (0)