Skip to content

Commit 5f02311

Browse files
zhuizhuhaomengguanglinlv
and
guanglinlv
authored
feature: ssl/tls: support for passphrase protected key. (openresty#1991)
Co-authored-by: guanglinlv <[email protected]>
1 parent 7eb8ad0 commit 5f02311

File tree

4 files changed

+214
-6
lines changed

4 files changed

+214
-6
lines changed

src/ngx_http_lua_ssl_certby.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ ngx_http_lua_ffi_cert_pem_to_der(const u_char *pem, size_t pem_len, u_char *der,
10421042

10431043
int
10441044
ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len,
1045-
u_char *der, char **err)
1045+
const u_char *passphrase, u_char *der, char **err)
10461046
{
10471047
int len;
10481048
BIO *in;
@@ -1055,7 +1055,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len,
10551055
return NGX_ERROR;
10561056
}
10571057

1058-
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
1058+
pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, (void *) passphrase);
10591059
if (pkey == NULL) {
10601060
BIO_free(in);
10611061
*err = "PEM_read_bio_PrivateKey() failed";

t/140-ssl-c-api.t

Lines changed: 177 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ffi.cdef[[
3636
size_t pem_len, unsigned char *der, char **err);
3737
3838
int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem,
39-
size_t pem_len, unsigned char *der, char **err);
39+
size_t pem_len, const unsigned char *passphrase,
40+
unsigned char *der, char **err);
4041
4142
int ngx_http_lua_ffi_ssl_set_der_certificate(void *r,
4243
const char *data, size_t len, char **err);
@@ -130,7 +131,7 @@ __DATA__
130131
131132
out = ffi.new("char [?]", #pkey)
132133
133-
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
134+
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
134135
if rc < 1 then
135136
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
136137
ffi.string(errmsg[0]))
@@ -284,7 +285,7 @@ lua ssl server name: "test.com"
284285
285286
out = ffi.new("char [?]", #pkey)
286287
287-
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
288+
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
288289
if rc < 1 then
289290
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
290291
ffi.string(errmsg[0]))
@@ -422,7 +423,7 @@ lua ssl server name: "test.com"
422423
423424
out = ffi.new("char [?]", #pkey)
424425
425-
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, out, errmsg)
426+
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, nil, out, errmsg)
426427
if rc < 1 then
427428
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
428429
ffi.string(errmsg[0]))
@@ -1024,3 +1025,175 @@ client certificate subject: nil
10241025
--- no_error_log
10251026
[error]
10261027
[alert]
1028+
1029+
1030+
1031+
=== TEST 9: simple cert + private key with passphrase
1032+
--- http_config
1033+
server {
1034+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
1035+
server_name test.com;
1036+
1037+
ssl_certificate_by_lua_block {
1038+
collectgarbage()
1039+
1040+
local ffi = require "ffi"
1041+
1042+
ffi.cdef[[
1043+
int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem,
1044+
size_t pem_len, unsigned char *der, char **err);
1045+
1046+
int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem,
1047+
size_t pem_len, const unsigned char *passphrase,
1048+
unsigned char *der, char **err);
1049+
1050+
int ngx_http_lua_ffi_ssl_set_der_certificate(void *r,
1051+
const char *data, size_t len, char **err);
1052+
1053+
int ngx_http_lua_ffi_ssl_set_der_private_key(void *r,
1054+
const char *data, size_t len, char **err);
1055+
1056+
int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err);
1057+
]]
1058+
1059+
local errmsg = ffi.new("char *[1]")
1060+
1061+
local r = require "resty.core.base" .get_request()
1062+
if not r then
1063+
ngx.log(ngx.ERR, "no request found")
1064+
return
1065+
end
1066+
1067+
ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg)
1068+
1069+
local f = assert(io.open("t/cert/test_passphrase.crt", "rb"))
1070+
local cert = f:read("*all")
1071+
f:close()
1072+
1073+
local out = ffi.new("char [?]", #cert)
1074+
1075+
local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg)
1076+
if rc < 1 then
1077+
ngx.log(ngx.ERR, "failed to parse PEM cert: ",
1078+
ffi.string(errmsg[0]))
1079+
return
1080+
end
1081+
1082+
local cert_der = ffi.string(out, rc)
1083+
1084+
local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg)
1085+
if rc ~= 0 then
1086+
ngx.log(ngx.ERR, "failed to set DER cert: ",
1087+
ffi.string(errmsg[0]))
1088+
return
1089+
end
1090+
1091+
f = assert(io.open("t/cert/test_passphrase.key", "rb"))
1092+
local pkey = f:read("*all")
1093+
f:close()
1094+
1095+
local passphrase = "123456"
1096+
1097+
out = ffi.new("char [?]", #pkey)
1098+
1099+
local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der(pkey, #pkey, passphrase, out, errmsg)
1100+
if rc < 1 then
1101+
ngx.log(ngx.ERR, "failed to parse PEM priv key: ",
1102+
ffi.string(errmsg[0]))
1103+
return
1104+
end
1105+
1106+
local pkey_der = ffi.string(out, rc)
1107+
1108+
local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg)
1109+
if rc ~= 0 then
1110+
ngx.log(ngx.ERR, "failed to set DER priv key: ",
1111+
ffi.string(errmsg[0]))
1112+
return
1113+
end
1114+
}
1115+
1116+
ssl_certificate ../../cert/test2.crt;
1117+
ssl_certificate_key ../../cert/test2.key;
1118+
1119+
server_tokens off;
1120+
location /foo {
1121+
default_type 'text/plain';
1122+
content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
1123+
more_clear_headers Date;
1124+
}
1125+
}
1126+
--- config
1127+
server_tokens off;
1128+
lua_ssl_trusted_certificate ../../cert/test_passphrase.crt;
1129+
1130+
location /t {
1131+
content_by_lua_block {
1132+
do
1133+
local sock = ngx.socket.tcp()
1134+
1135+
sock:settimeout(2000)
1136+
1137+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
1138+
if not ok then
1139+
ngx.say("failed to connect: ", err)
1140+
return
1141+
end
1142+
1143+
ngx.say("connected: ", ok)
1144+
1145+
local sess, err = sock:sslhandshake(nil, "test.com", false)
1146+
if not sess then
1147+
ngx.say("failed to do SSL handshake: ", err)
1148+
return
1149+
end
1150+
1151+
ngx.say("ssl handshake: ", type(sess))
1152+
1153+
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
1154+
local bytes, err = sock:send(req)
1155+
if not bytes then
1156+
ngx.say("failed to send http request: ", err)
1157+
return
1158+
end
1159+
1160+
ngx.say("sent http request: ", bytes, " bytes.")
1161+
1162+
while true do
1163+
local line, err = sock:receive()
1164+
if not line then
1165+
-- ngx.say("failed to recieve response status line: ", err)
1166+
break
1167+
end
1168+
1169+
ngx.say("received: ", line)
1170+
end
1171+
1172+
local ok, err = sock:close()
1173+
ngx.say("close: ", ok, " ", err)
1174+
end -- do
1175+
-- collectgarbage()
1176+
}
1177+
}
1178+
1179+
--- request
1180+
GET /t
1181+
--- response_body
1182+
connected: 1
1183+
ssl handshake: userdata
1184+
sent http request: 56 bytes.
1185+
received: HTTP/1.1 201 Created
1186+
received: Server: nginx
1187+
received: Content-Type: text/plain
1188+
received: Content-Length: 4
1189+
received: Connection: close
1190+
received:
1191+
received: foo
1192+
close: 1 nil
1193+
1194+
--- error_log
1195+
lua ssl server name: "test.com"
1196+
1197+
--- no_error_log
1198+
[error]
1199+
[alert]

t/cert/test_passphrase.crt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICozCCAgwCCQDEutRdSs3vZjANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMC
3+
Q04xEjAQBgNVBAgMCUd1YW5nZG9uZzERMA8GA1UEBwwIU2hlblpoZW4xEjAQBgNV
4+
BAoMCU9wZW5SZXN0eTESMBAGA1UECwwJT3BlblJlc3R5MREwDwYDVQQDDAh0ZXN0
5+
LmNvbTEjMCEGCSqGSIb3DQEJARYUZ3VhbmdsaW5sdkBnbWFpbC5jb20wIBcNMTYw
6+
NDI4MTQ0MzI4WhgPMjE1MTAzMjcxNDQzMjhaMIGUMQswCQYDVQQGEwJDTjESMBAG
7+
A1UECAwJR3Vhbmdkb25nMREwDwYDVQQHDAhTaGVuWmhlbjESMBAGA1UECgwJT3Bl
8+
blJlc3R5MRIwEAYDVQQLDAlPcGVuUmVzdHkxETAPBgNVBAMMCHRlc3QuY29tMSMw
9+
IQYJKoZIhvcNAQkBFhRndWFuZ2xpbmx2QGdtYWlsLmNvbTCBnzANBgkqhkiG9w0B
10+
AQEFAAOBjQAwgYkCgYEA2KZ+HdH9R2tarxD8PKqu5EYq2BNGlFRg1xJmrw0XZBRM
11+
UP/VPb+sIeioooz36uhiXfQjExlpBCA/0zNAN+HbFyqpPPTf1qLGrj/dqeE4MJaN
12+
Bwzxiv3fZnENT65u2qbiFWIY+ATNHgA20d50nxNNjPTzLbkx/nYXL92r4kuAGk0C
13+
AwEAATANBgkqhkiG9w0BAQUFAAOBgQCfMo0qbcs3kwl1tcNBO5hCcUUJRzyv041V
14+
ff/nZ/JPIMo/LSZd12K82G/dLRN7uRT9nzqtm+JRkHALHWWWFKi6bdg1vcdOTWqC
15+
08bCkJHQoXJQQLvvA6gNvnR+0b7L4CrCmrcyYgKDLXVGNP9Wv/PqSWWbxsmqngkA
16+
Mvy6CVytFw==
17+
-----END CERTIFICATE-----

t/cert/test_passphrase.key

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
Proc-Type: 4,ENCRYPTED
3+
DEK-Info: DES-EDE3-CBC,679ACC8E69ACAA92
4+
5+
Ssrjp3VU4somCNPiXkWqcudDnvnwbyj/Q0pS07at3lXKbhQSgI1Tzhg9Pm3BXXj5
6+
mkLdeGG5ocrj1Q9dhtmZgZeHHQIiynZBhjBu1Y+HPef8jXOWLrCOi8EKiWkJ2qG3
7+
V1KFM/95CcDt0mRLykUXEL3IpUst05SFb9XwiLokB7ypeu3NhgNUHjL6G+ubB4ri
8+
TOUjCW4pEoNHjdC22IiqSncwCVhluYSGhr6ktHKehZMhYIXmL1wmSLdhTlsPXCQl
9+
xvYILQ2vJcKIR1BkeYYPD/OQC6zCZlXIErzfgeZiz2+NTudKYpb9VmsQKsO+R8L7
10+
tZ/fNaR0vk8bbimMHgStAV4acVsC/7WxsqOjMJ8VTq1iqhYPl6N7kRdR3H3kSSOm
11+
cN9T3SrOHDVaHbnWgToaOE4mKFjvFSLIOcWgus0iOHWXmY+SLG+Ndag3oVB6R9oB
12+
cAHX19mq99+GhzA8IV4I0En2UCKQhnGPvkM+9mcCDxhRETlwncDjlMGOHpQ65J9r
13+
eReVPIpnDkvHxPGTtsR3ZHTdWTZb+C0W2N3QIlJKrOzxFmfoj++yG3tMX42aDY0g
14+
DVkrXgcKobiWN0AVrJNAwfG7uObKSCFYgz/0RRMCO4cjXRW99nxdjVDZhyc6R0Te
15+
jzuF04okkOLNb25n2hP+yIULrn+6Nv/uHtFI0j0n3hOzcKh//dNbACSAKgkHni9g
16+
JKDFJXgLJxf+Wc3So0DF9gYMKJJ+WbcdVT9gkC7RyQHlC90Pn7kNXzHr0ZawUsNI
17+
ZxSkL4dMhYAfA4lUBJbOkwbSurv97LinOSRffpM0Nmf7VNw/Ue15eg==
18+
-----END RSA PRIVATE KEY-----

0 commit comments

Comments
 (0)