@@ -4062,10 +4062,33 @@ 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 is encrypted
4073+ * and its type is not specified. The user-provided function is called only
4074+ * once because it gets replaced on the stack by the return value. This
4075+ * callback may not be called at all if the supplied PEM key is not encrypted.
4076+ */
40654077static int pem_pw_cb (char * buf , int size , int rwflag , void * u ) {
4066- if (!u )
4078+ lua_State * L = (lua_State * ) u ;
4079+
4080+ if (lua_isfunction (L , -1 ) && lua_pcall (L , 0 , 1 , 0 )) {
4081+ lua_pop (L , 1 );
4082+ lua_pushnil (L );
4083+ }
4084+
4085+ if (lua_isnil (L , -1 ))
40674086 return 0 ;
4068- char * pass = (char * ) u ;
4087+
4088+ const char * pass = lua_tostring (L , -1 );
4089+ if (!pass )
4090+ return 0 ;
4091+
40694092 strncpy (buf , pass , size );
40704093 return MIN (strlen (pass ), (unsigned int ) size );
40714094} /* pem_pw_cb() */
@@ -4310,7 +4333,7 @@ static int pk_new(lua_State *L) {
43104333 } else if (lua_isstring (L , 1 )) {
43114334 int format ;
43124335 int pubonly = 0 , prvtonly = 0 ;
4313- const char * type , * data , * pass ;
4336+ const char * type , * data ;
43144337 size_t len ;
43154338 BIO * bio ;
43164339 EVP_PKEY * pub = NULL , * prvt = NULL ;
@@ -4341,8 +4364,7 @@ static int pk_new(lua_State *L) {
43414364 }
43424365 }
43434366
4344- pass = luaL_optstring (L , 4 , NULL );
4345- if (pass ) {
4367+ if (!lua_isnil (L , 4 )) {
43464368 if (format == X509_DER )
43474369 return luaL_error (L , "decryption supported only for PEM keys" );
43484370 else format = X509_PEM ;
@@ -4354,6 +4376,8 @@ static int pk_new(lua_State *L) {
43544376 return auxL_error (L , auxL_EOPENSSL , "pkey.new" );
43554377
43564378 if (format == X509_PEM || format == X509_ANY ) {
4379+ lua_pushvalue (L , 4 );
4380+
43574381 if (!prvtonly && !pub ) {
43584382 /*
43594383 * BIO_reset is a rewind for read-only
@@ -4362,16 +4386,18 @@ static int pk_new(lua_State *L) {
43624386 */
43634387 BIO_reset (bio );
43644388
4365- if (!(pub = PEM_read_bio_PUBKEY (bio , NULL , pem_pw_cb , pass )))
4389+ if (!(pub = PEM_read_bio_PUBKEY (bio , NULL , pem_pw_cb , L )))
43664390 goterr = 1 ;
43674391 }
43684392
43694393 if (!pubonly && !prvt ) {
43704394 BIO_reset (bio );
43714395
4372- if (!(prvt = PEM_read_bio_PrivateKey (bio , NULL , pem_pw_cb , pass )))
4396+ if (!(prvt = PEM_read_bio_PrivateKey (bio , NULL , pem_pw_cb , L )))
43734397 goterr = 1 ;
43744398 }
4399+
4400+ lua_pop (L , 1 );
43754401 }
43764402
43774403 if (format == X509_DER || format == X509_ANY ) {
@@ -4712,7 +4738,6 @@ static int pk_toPEM(lua_State *L) {
47124738 int type ;
47134739 const char * cname = NULL ;
47144740 const EVP_CIPHER * cipher = NULL ;
4715- const char * pass = NULL ;
47164741
47174742 if (lua_istable (L , i )) {
47184743 loadfield (L , i , "cipher" , LUA_TSTRING , & cname );
@@ -4739,13 +4764,17 @@ static int pk_toPEM(lua_State *L) {
47394764 cipher = EVP_get_cipherbyname (cname );
47404765 if (!cipher )
47414766 return luaL_error (L , "pkey:toPEM: unknown cipher: %s" , cname );
4742- if (!loadfield (L , i , "password" , LUA_TSTRING , & pass ))
4767+ if (!getfield (L , i , "password" ))
47434768 return luaL_error (L , "pkey:toPEM: password not defined" );
47444769 }
4770+ else
4771+ lua_pushnil (L );
47454772
4746- if (!PEM_write_bio_PrivateKey (bio , key , cipher , NULL , 0 , pem_pw_cb , pass ))
4773+ if (!PEM_write_bio_PrivateKey (bio , key , cipher , NULL , 0 , pem_pw_cb , L ))
47474774 return auxL_error (L , auxL_EOPENSSL , "pkey:__tostring" );
47484775
4776+ lua_pop (L , 1 );
4777+
47494778 len = BIO_get_mem_data (bio , & pem );
47504779 lua_pushlstring (L , pem , len );
47514780 BIO_reset (bio );
0 commit comments