Skip to content

feature: support load private key with password #973

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

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions src/ngx_http_lua_ssl_certby.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ static u_char *ngx_http_lua_log_ssl_cert_error(ngx_log_t *log, u_char *buf,
size_t len);
static ngx_int_t ngx_http_lua_ssl_cert_by_chunk(lua_State *L,
ngx_http_request_t *r);
static int ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag,
void *userdata);


ngx_int_t
Expand Down Expand Up @@ -557,6 +559,37 @@ ngx_http_lua_ffi_ssl_get_tls1_version(ngx_http_request_t *r, char **err)
}


static int
ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag,
void *userdata)
{
ngx_str_t *pwd = userdata;

if (rwflag) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
"ngx_http_lua_ssl_password_callback() "
"is called for encryption");
return 0;
}

if (pwd->len == 0) {
return 0;
}

if (pwd->len > (size_t) size) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"password is truncated to %d bytes", size);

} else {
size = pwd->len;
}

ngx_memcpy(buf, pwd->data, size);

return size;
}


int
ngx_http_lua_ffi_ssl_clear_certs(ngx_http_request_t *r, char **err)
{
Expand Down Expand Up @@ -982,6 +1015,51 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len,
}


int
ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const u_char *pem,
size_t pem_len, const u_char *pwd, size_t pwd_len, u_char *der, char **err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about reuse the current ngx_http_lua_ffi_priv_key_pem and pwd == NULL means without password?
So that we can reuse most of the code.

Copy link
Contributor Author

@detailyang detailyang Feb 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@doujiang24 I have considered the ngx_http_lua_ffi_priv_key_pem. But there are some existing tests which are rely on it. I'm not sure it's worth to change the ngx_http_lua_ffi_priv_key_pem. So just add the new api ngx_http_lua_ffi_priv_key_pem_to_der_with_password, then reimplement the Lua FFI API ngx.ssl.priv_key_pem_to_der to support password

So if we almost agree to reimplement the ngx_http_lua_ffi_priv_key_pem, I will try to do :D

{
int len;
BIO *in;
EVP_PKEY *pkey;
ngx_str_t password;

password.data = (u_char *) pwd;
password.len = pwd_len;

in = BIO_new_mem_buf((char *) pem, (int) pem_len);
if (in == NULL) {
*err = "BIO_new_mem_buf() failed";
ERR_clear_error();
return NGX_ERROR;
}

pkey = PEM_read_bio_PrivateKey(in, NULL,
ngx_http_lua_ssl_password_callback,
(void *) &password);
if (pkey == NULL) {
BIO_free(in);
*err = "PEM_read_bio_PrivateKey() failed";
ERR_clear_error();
return NGX_ERROR;
}

BIO_free(in);

len = i2d_PrivateKey(pkey, &der);
if (len < 0) {
EVP_PKEY_free(pkey);
*err = "i2d_PrivateKey() failed";
ERR_clear_error();
return NGX_ERROR;
}

EVP_PKEY_free(pkey);

return len;
}


void *
ngx_http_lua_ffi_parse_pem_cert(const u_char *pem, size_t pem_len,
char **err)
Expand Down Expand Up @@ -1102,6 +1180,40 @@ ngx_http_lua_ffi_parse_pem_priv_key(const u_char *pem, size_t pem_len,
}


void *
ngx_http_lua_ffi_parse_pem_priv_key_with_password(const u_char *pem,
size_t pem_len, const u_char *pwd, size_t pwd_len, char **err)
{
BIO *in;
EVP_PKEY *pkey;
ngx_str_t password;

password.data = (u_char *) pwd;
password.len = pwd_len;

in = BIO_new_mem_buf((char *) pem, (int) pem_len);
if (in == NULL) {
*err = "BIO_new_mem_buf() failed";
ERR_clear_error();
return NULL;
}

pkey = PEM_read_bio_PrivateKey(in, NULL,
ngx_http_lua_ssl_password_callback,
(void *) &password);
if (pkey == NULL) {
*err = "PEM_read_bio_PrivateKey() failed";
BIO_free(in);
ERR_clear_error();
return NULL;
}

BIO_free(in);

return pkey;
}


void
ngx_http_lua_ffi_free_priv_key(void *cdata)
{
Expand Down
Loading