-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for encrypted PEM keys #128
base: master
Are you sure you want to change the base?
Conversation
70d1c68
to
0a358f8
Compare
Please let me know if further changes are required to this patch set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of technical issues spotted; I still need to do a more thorough review.
src/openssl.c
Outdated
@@ -3674,6 +3687,8 @@ static int pk_new(lua_State *L) { | |||
} | |||
} | |||
|
|||
ud = prepsimple(L, PKEY_CLASS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can throw and leak bio
(which is why it was previously done before allocating bio
)
src/openssl.c
Outdated
char *pass = (char *) u; | ||
strncpy(buf, pass, size); | ||
return MIN(strlen(pass), (unsigned int) size); | ||
} /* pem_password_cb() */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess there is a typo in the comment. Should be /* pem_pw_cb() */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs fixing
src/openssl.c
Outdated
lua_settop(L, 3); | ||
|
||
if (cname) { | ||
cipher = EVP_get_cipherbyname(cname); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives a warning:
src/openssl.c: In function ‘pk_getPrivateKey’:
src/openssl.c:4132:10: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
cipher = EVP_get_cipherbyname(cname);
^
So this PR works, but I've found it very odd to use. e.g. here is a valid invocation: pk=require "openssl.pkey"
a=pk.new()
k=a:getPrivateKey("aes-256-cbc", "bar")
b = pk.new(k, "PEM", "private", "bar") But the following invocations fail (with mostly hard to understand/debug error messages) Passing "public" rather than "private":
Passing wrong password (this is probably fine):
Passing wrong password and also no public vs private:
Passing wrong password and no "PEM" choice:
Otherwise, I found it troublesome that not passing a cipher would result in no password being used. |
I was thinking if the API could be something like this: pk = require "openssl.pkey" a = pk.new() k = a:toPEM{type="private", cipher="aes-256-cbc", password="bar"} b = pk.new(k, {format="PEM", type="private", password="bar"}) This would make the code more readable and there would be no need for a separate |
The new patch set implements passing options via a table as suggested above, avoiding the need for a new |
@kunkku - Is this patch safe to use ? are there any further changes expected ? |
Honestly, I do not know. I would like to get feedback from the maintainers. |
src/openssl.c
Outdated
char *pass = (char *) u; | ||
strncpy(buf, pass, size); | ||
return MIN(strlen(pass), (unsigned int) size); | ||
} /* pem_password_cb() */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs fixing
src/openssl.c
Outdated
lua_State *L = (lua_State *) u; | ||
|
||
if (lua_isnil(L, -1) || (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0))) | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't keep the stack balanced: if the field is nil then nothing is pushed. If the pcall
results in an error then the error will be left on the stack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this should work?
diff --git a/src/openssl.c b/src/openssl.c
index 35183ab..868a6d3 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -4073,9 +4073,14 @@ static BIO *getbio(lua_State *L) {
static int pem_pw_cb(char *buf, int size, int rwflag, void *u) {
lua_State *L = (lua_State *) u;
- if (lua_isnil(L, -1) || (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0)))
+ if (lua_isnil(L, -1))
return 0;
+ if (lua_isfunction(L, -1) && lua_pcall(L, 0, 1, 0)) {
+ lua_pop(L, 1);
+ return 0;
+ }
+
const char *pass = lua_tostring(L, -1);
if (!pass)
return 0;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check the current implementation. In case of error, the error is replaced by nil
to make the callback return directly if called again. The callback does not change the size of the stack on any execution path.
wahern/luaossl#128 backwards incompatible
lua_getfield(L, 2, "type"); | ||
lua_getfield(L, 2, "password"); | ||
} else | ||
lua_pushnil(L); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This branch only pushes one item vs the other branch's 3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now the net amount of pushed items is 1 in both branches.
@@ -4062,10 +4070,31 @@ static BIO *getbio(lua_State *L) { | |||
} /* getbio() */ | |||
|
|||
|
|||
static int pem_pw_cb(char *buf, int size, int rwflag, void *u) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth adding a comment of "expects nil/function/string on top of the stack" and "leaves one item on the top of the stack".
"errors from the function are not reported"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps it should leave nothing on the stack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Requested comments added.
return luaL_error(L, "pkey:toPEM: password not defined"); | ||
} | ||
|
||
if (!PEM_write_bio_PrivateKey(bio, key, cipher, NULL, 0, pem_pw_cb, L)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there is no cname on the stack then what will be at top of stack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an else branch which pushes a nil value. The value will not be used because openssl will not invoke the callback when cipher equals NULL.
dd01937
to
005b8bf
Compare
size_t len; | ||
BIO *bio; | ||
EVP_PKEY *pub = NULL, *prvt = NULL; | ||
int goterr = 0; | ||
|
||
if (lua_istable(L, 2)) { | ||
lua_pop(L, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be popping the table itself; or the 3rd argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is always the 3rd argument because stack size is set to 3 on line 4101. Of course, this can be changed to lua_remove if you prefer it that way.
|
||
/* #1 key, #2 format, #3 type, #4 password or callback */ | ||
|
||
data = luaL_checklstring(L, 1, &len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the error message for this will have the wrong index
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should it be then? This was just moved from line 4321 to process the arguments in ascending order. The purpose was to improve readability.
No description provided.