Squashed 'src/deps/src/lua-resty-openssl/' changes from 643956d99..e56da6c5f

e56da6c5f release: 1.4.0
91a30f698 feat(pkey) allow pkey.new to compose from parameters
0016308c9 feat(pkey) add pkey:verify_raw
2093e8814 fix(ec) add missing cdef for EC_POINT_free
9ad27e2bb chore(deps): bump jinja2 from 3.1.3 to 3.1.4 in /scripts
eed8b4fbf chore(aux/nginx) clarify the error message of usage of development mode
86068aacd chore(tests) update openssl fips provider to 3.0.9
66c49b164 chore(tests) add openssl 3.3.0 in matrix

git-subtree-dir: src/deps/src/lua-resty-openssl
git-subtree-split: e56da6c5f285ff0e40fce703b870e83ee8eac321
This commit is contained in:
Théophile Diot 2024-05-27 15:17:05 +01:00
parent 2d8549ef17
commit a6a40ab74b
14 changed files with 259 additions and 28 deletions

View file

@ -30,14 +30,14 @@ jobs:
# latest and one version older for valgrind and perf test
- nginx: "1.19.9"
openssl: "3.1.5"
openssl_fips: "3.0.8"
openssl_fips: "3.0.9"
extras: "valgrind"
lua_nginx_module: "v0.10.20"
lua_resty_core: "v0.1.22"
nginx_cc_opts: "-Wno-error"
- nginx: "1.21.4"
openssl: "3.1.5"
openssl_fips: "3.0.8"
openssl_fips: "3.0.9"
extras: "valgrind"
lua_nginx_module: "v0.10.25"
lua_resty_core: "v0.1.27"
@ -49,25 +49,33 @@ jobs:
lua_resty_core: "v0.1.28"
- nginx: "1.25.3"
openssl: "3.0.13"
openssl_fips: "3.0.8"
openssl_fips: "3.0.9"
extras: "valgrind perf lua-kong-nginx-module"
lua_nginx_module: "v0.10.26"
lua_resty_core: "v0.1.28"
nginx_cc_opts: "-Wno-error"
- nginx: "1.25.3"
openssl: "3.1.5"
openssl_fips: "3.0.8"
openssl_fips: "3.0.9"
extras: "valgrind perf lua-kong-nginx-module"
lua_nginx_module: "v0.10.26"
lua_resty_core: "v0.1.28"
nginx_cc_opts: "-Wno-error"
- nginx: "1.25.3"
openssl: "3.2.1"
openssl_fips: "3.0.8"
openssl_fips: "3.0.9"
extras: "valgrind perf lua-kong-nginx-module"
lua_nginx_module: "v0.10.26"
lua_resty_core: "v0.1.28"
nginx_cc_opts: "-Wno-error"
- nginx: "1.25.3"
openssl: "3.3.0"
openssl_fips: "3.0.9"
extras: "valgrind perf lua-kong-nginx-module"
lua_nginx_module: "v0.10.26"
lua_resty_core: "v0.1.28"
nginx_cc_opts: "-Wno-error"
env:
JOBS: 3

View file

@ -2,12 +2,22 @@
## [Unreleased]
<a name="1.4.0"></a>
## [1.4.0] - 2024-05-27
### bug fixes
- **ec:** add missing cdef for EC_POINT_free [2093e88](https://github.com/fffonion/lua-resty-openssl/commit/2093e8814ccfbe830ba594a71f05870cac208e9c)
### features
- **pkey:** allow pkey.new to compose from parameters [91a30f6](https://github.com/fffonion/lua-resty-openssl/commit/91a30f6988e3fc696363ce1445b49a3f6ee8f35e)
- **pkey:** add pkey:verify_raw [0016308](https://github.com/fffonion/lua-resty-openssl/commit/0016308c9e3a2ccfdfe674ede64e462060f7b13b)
<a name="1.3.1"></a>
## [1.3.1] - 2024-04-22
### bug fixes
- **aux/jwk:** remove ecx.d if exporting as public key [9d34ff8](https://github.com/fffonion/lua-resty-openssl/commit/9d34ff8fd79debbcf155f74af0b161083b6a8385)
- **aux/nginx:** fix the typo of get_socket_ssl in the stream module [0aa315e](https://github.com/fffonion/lua-resty-openssl/commit/0aa315efe3d98d38d8d77dedf687958b62d8b184)
- **aux/nginx:** remove extra sanity test that prevent usage of lua-kong-nginx-module [7bd2d0a](https://github.com/fffonion/lua-resty-openssl/commit/7bd2d0aabe82219071fe9fd1b30e49ff88bd5472)
- **aux/nginx:** fix the typo of get_socket_ssl in the stream module [ad18b3c](https://github.com/fffonion/lua-resty-openssl/commit/ad18b3c18c7ec3db175aabfbf6928141c3b53b17)
- **aux/nginx:** remove extra sanity test that prevent usage of lua-kong-nginx-module [2323526](https://github.com/fffonion/lua-resty-openssl/commit/2323526766b131bde94052449c41a331e93288bd)
<a name="1.3.0"></a>
@ -591,7 +601,8 @@
- **x509:** export pubkey [ede4f81](https://github.com/fffonion/lua-resty-openssl/commit/ede4f817cb0fe092ad6f9ab5d6ecdcde864a9fd8)
[Unreleased]: https://github.com/fffonion/lua-resty-openssl/compare/1.3.1...HEAD
[Unreleased]: https://github.com/fffonion/lua-resty-openssl/compare/1.4.0...HEAD
[1.4.0]: https://github.com/fffonion/lua-resty-openssl/compare/1.3.1...1.4.0
[1.3.1]: https://github.com/fffonion/lua-resty-openssl/compare/1.3.0...1.3.1
[1.3.0]: https://github.com/fffonion/lua-resty-openssl/compare/1.2.1...1.3.0
[1.2.1]: https://github.com/fffonion/lua-resty-openssl/compare/1.2.0...1.2.1

View file

@ -66,6 +66,7 @@ Table of Contents
+ [pkey:encrypt](#pkeyencrypt)
+ [pkey:decrypt](#pkeydecrypt)
+ [pkey:sign_raw](#pkeysign_raw)
+ [pkey:verify_raw](#pkeyverify_raw)
+ [pkey:verify_recover](#pkeyverify_recover)
+ [pkey:derive](#pkeyderive)
+ [pkey:tostring](#pkeytostring)
@ -871,13 +872,14 @@ for EC keys. See [pkey:sign](#pkeysign) and [pkey.verify](#pkeyverify) for detai
- When running outside of OpenResty, needs to install a JSON library (`cjson` or `dkjson`)
and `basexx`.
[Back to TOC](#table-of-contents)
#### Key generation
**syntax**: *pk, err = pkey.new(config?)*
Generate a new public key or private key.
To generate RSA key, `config` table can have `bits` and `exp` field to control key generation.
When `config` is emitted, this function generates a 2048 bit RSA key with `exponent` of 65537,
which is equivalent to:
@ -936,6 +938,27 @@ pkey.new({
```
[Back to TOC](#table-of-contents)
#### Key composition
**syntax**: *pk, err = pkey.new(config?)*
Compose a public or private key using existing parameters. To see
list of parameters for each key, refer to [pkey:set_parameters](#pkeyset_parameters).
Only `type` and `params` should exist in `config` table, all other keys will be ignored.
```lua
local private_bn = require "resty.openssl.bn".new("7F48282CCA4C1A65D589C06DBE9C42AE50FBFFDF3A18CBB48498E1DE47F11BE1A3486CD8FA950D68F111970F922279D8", 16)
local p_384, err = assert(require("resty.openssl.pkey").new({
type = "EC",
params = {
private = private_bn,
group = "secp384r1",
}
}))
```
[Back to TOC](#table-of-contents)
@ -1195,6 +1218,8 @@ pk:sign(message, nil, nil, {
-- in pkeyutl CLI the above is equivalent to: `openssl pkeyutl -sign -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
```
To sign a message without doing message digest, please check [pkey:sign_raw](#pkeysign_raw).
[Back to TOC](#table-of-contents)
### pkey:verify
@ -1262,6 +1287,8 @@ ngx.say(ngx.encode_base64(signature))
```
To verify a message without doing message digest, please check [pkey:verify_raw](#pkeyverify_raw) and [pkey:verify_recover](#pkeyverify_recover).
[Back to TOC](#table-of-contents)
### pkey:encrypt
@ -1325,6 +1352,25 @@ for an example.
[Back to TOC](#table-of-contents)
### pkey:verify_raw
**syntax**: *ok, err = pk:verify_raw(signature, data, md_alg, padding?, opts?)*
Verify the cipher text `signature` with the message `data` with pkey instance, which must loaded a public key. Set the message digest to `md_alg` but doesn't do message digest
automatically, in other words, this function assumes `data` has already been hashed with `md_alg`.
When `md_alg` is undefined, for RSA and EC keys, this function does SHA256 by default. For Ed25519 or Ed448 keys, no default value is set.
The optinal fourth argument `padding` has same meaning as in [pkey:sign](#pkeysign).
If omitted, `padding` is default to `pkey.PADDINGS.RSA_PKCS1_PADDING`.
The fifth optional argument `opts` has same meaning as in [pkey:sign](#pkeysign).
See [examples/raw-sign-and-recover.lua](https://github.com/fffonion/lua-resty-openssl/blob/master/examples/raw-sign-and-recover.lua)
for an example.
[Back to TOC](#table-of-contents)
### pkey:verify_recover
**syntax**: *txt, err = pk:verify_recover(signature, padding?, opts?)*

View file

@ -7,11 +7,29 @@ local original = "original text"
-- same as nodejs: crypto.privateEncrypt
-- php: openssl_private_encrypt
local digested = assert(priv:sign_raw(original))
local signed = assert(priv:sign_raw(original))
print("Digested message: " .. ngx.encode_base64(digested))
print("Signed message: " .. ngx.encode_base64(signed))
-- same as nodejs: crypto.publicDecrypt
-- php: openssl_public_decrypt
local recovered = assert(pub:verify_recover(digested))
local recovered = assert(pub:verify_recover(signed))
print("Recovered message: " .. recovered)
local priv = assert(pkey.new({
type = "EC",
}))
local pub = assert(pkey.new(priv:to_PEM("public")))
local md_alg = "sha512"
local hashed = require "resty.openssl.digest".new(md_alg):final(original)
local signed = assert(priv:sign_raw(hashed))
print("Signed message: " .. ngx.encode_base64(signed))
-- same as nodejs: crypto.publicDecrypt
-- php: openssl_public_decrypt
local verified = assert(pub:verify_raw(signed, hashed, md_alg))
print("Verification result: ", verified)

View file

@ -24,7 +24,7 @@ try_require_modules()
local _M = {
_VERSION = '1.3.1',
_VERSION = '1.4.0',
}
function _M.load_modules()

View file

@ -177,6 +177,7 @@ function _M.load_jwk(txt)
if key ~= nil then
return key
end
key_free = function() end
else
return nil, "not yet supported jwk type \"" .. (tbl["kty"] or "nil") .. "\""
end

View file

@ -125,7 +125,8 @@ else
} ngx_connection_s;
]]
else
error("resty.openssl.auxiliary.nginx doesn't support Nginx version " .. ngx_version, 2)
error("resty.openssl.auxiliary.nginx development mode doesn't support Nginx version " .. ngx_version ..
", please compile nginx with lua-resty-openssl-aux-module or lua-kong-nginx-module.", 2)
end
ffi.cdef [[
@ -167,7 +168,8 @@ else
local NO_C_MODULE_WARNING_MSG_SHOWN = false
local NO_C_MODULE_WARNING_MSG = "note resty.openssl.auxiliary.nginx is using plain FFI " ..
"and it's only intended to be used in development, " ..
"consider using lua-resty-openssl.aux-module in production."
"consider using lua-resty-openssl-aux-module or " ..
"lua-kong-nginx-module in production."
local function get_ngx_ssl_from_req()
if not NO_C_MODULE_WARNING_MSG_SHOWN then

View file

@ -158,6 +158,8 @@ function _M.set_parameters(ec_key_st, opts)
end
end
return true
end
return _M

View file

@ -34,6 +34,7 @@ ffi.cdef [[
BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn,
EC_POINT *p, BN_CTX *ctx);
void EC_POINT_free(EC_POINT *point);
point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);

View file

@ -41,6 +41,10 @@ ffi.cdef [[
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,

View file

@ -402,6 +402,67 @@ local function generate_key(config)
return ctx_ptr[0]
end
local function compose_key(config)
local typ = config.type or 'RSA'
local key_type
if typ == "RSA" then
key_type = evp_macro.EVP_PKEY_RSA
elseif typ == "EC" then
key_type = evp_macro.EVP_PKEY_EC
elseif evp_macro.ecx_curves[typ] then
key_type = evp_macro.ecx_curves[typ]
else
return nil, "unsupported type " .. typ
end
if key_type == 0 then
return nil, "the linked OpenSSL library doesn't support " .. typ .. " key"
end
local key, err, key_free, _
if key_type == evp_macro.EVP_PKEY_EC then
key = C.EC_KEY_new()
if key == nil then
return nil, "EC_KEY_new failed"
end
key_free = C.EC_KEY_free
_, err = ec_lib.set_parameters(key, config.params)
elseif key_type == evp_macro.EVP_PKEY_RSA then
key = C.RSA_new()
if key == nil then
return nil, "RSA_new failed"
end
key_free = C.RSA_free
_, err = rsa_lib.set_parameters(key, config.params)
elseif key_type == evp_macro.EVP_PKEY_ED25519 or
key_type == evp_macro.EVP_PKEY_X25519 or
key_type == evp_macro.EVP_PKEY_ED448 or
key_type == evp_macro.EVP_PKEY_X448 then
key_free = function() end
key, err = ecx_lib.set_parameters(key_type, nil, config.params)
end
if err then
return nil, "failed to construct " .. typ.. " key from parameters: " .. err
end
local ctx = C.EVP_PKEY_new()
if ctx == nil then
key_free(key)
return nil, "EVP_PKEY_new() failed"
end
local code = C.EVP_PKEY_assign(ctx, key_type, key)
if code ~= 1 then
key_free(key)
C.EVP_PKEY_free(ctx)
return nil, "EVP_PKEY_assign() failed"
end
return ctx
end
local load_key_try_funcs = {} do
-- TODO: pkcs1 load functions are not required in openssl 3.0
local _load_key_try_funcs = {
@ -506,9 +567,13 @@ function _M.new(s, opts)
local ctx, err
s = s or {}
if type(s) == 'table' then
ctx, err = generate_key(s)
if s.params then
ctx, err = compose_key(s)
else
ctx, err = generate_key(s)
end
if err then
err = "pkey.new:generate_key: " .. err
err = "pkey.new:new_key: " .. err
end
elseif type(s) == 'string' then
ctx, err = load_pem_der(s, opts or empty_table, load_key_try_funcs)
@ -656,8 +721,9 @@ end
local ASYMMETRIC_OP_ENCRYPT = 0x1
local ASYMMETRIC_OP_DECRYPT = 0x2
local ASYMMETRIC_OP_SIGN_RAW = 0x4
local ASYMMETRIC_OP_VERIFY_RECOVER = 0x8
local ASYMMETRIC_OP_SIGN_RAW = 0x3
local ASYMMETRIC_OP_VERIFY_RAW = 0x4
local ASYMMETRIC_OP_VERIFY_RECOVER = 0x5
local function asymmetric_routine(self, s, op, padding, opts)
if type(s) ~= "string" then
@ -701,6 +767,10 @@ local function asymmetric_routine(self, s, op, padding, opts)
fint = C.EVP_PKEY_sign_init
f = C.EVP_PKEY_sign
op_name = "sign"
elseif op == ASYMMETRIC_OP_VERIFY_RAW then
fint = C.EVP_PKEY_verify_init
f = C.EVP_PKEY_verify
op_name = "verify"
elseif op == ASYMMETRIC_OP_VERIFY_RECOVER then
fint = C.EVP_PKEY_verify_recover_init
f = C.EVP_PKEY_verify_recover
@ -725,13 +795,25 @@ local function asymmetric_routine(self, s, op, padding, opts)
return nil, "pkey:asymmetric_routine: " .. err
end
local length = ptr_of_size_t(self.buf_size)
if f(pkey_ctx, self.buf, length, s, #s) <= 0 then
return nil, format_error("pkey:asymmetric_routine EVP_PKEY_" .. op_name)
local buf, buf_len
if opts and opts.buf_in then
buf = opts.buf_in
buf_len = #buf
else
buf = self.buf
buf_len = ptr_of_size_t(self.buf_size)
end
return ffi_str(self.buf, length[0]), nil
code = f(pkey_ctx, buf, buf_len, s, #s)
if code <= 0 then
return nil, format_error("pkey:asymmetric_routine EVP_PKEY_" .. op_name, code)
end
if not opts or not opts.buf_in then
return ffi_str(self.buf, buf_len[0]), nil
end
return true
end
_M.PADDINGS = rsa_macro.paddings
@ -753,6 +835,16 @@ function _M:sign_raw(s, padding, opts)
return asymmetric_routine(self, s, ASYMMETRIC_OP_SIGN_RAW, padding, opts)
end
function _M:verify_raw(signature, hashed_message, md_alg, padding, opts)
opts = opts or {}
opts.buf_in = signature
if md_alg then
table.insert(opts, "digest:" .. md_alg)
end
return asymmetric_routine(self, hashed_message, ASYMMETRIC_OP_VERIFY_RAW, padding, opts)
end
function _M:verify_recover(s, padding, opts)
return asymmetric_routine(self, s, ASYMMETRIC_OP_VERIFY_RECOVER, padding, opts)
end

View file

@ -1,8 +1,8 @@
package = "lua-resty-openssl"
version = "1.3.1-1"
version = "1.4.0-1"
source = {
url = "git+https://github.com/fffonion/lua-resty-openssl.git",
tag = "1.3.1"
tag = "1.4.0"
}
description = {
detailed = "FFI-based OpenSSL binding for LuaJIT.",

View file

@ -1 +1 @@
jinja2==3.1.3
jinja2==3.1.4

View file

@ -225,6 +225,39 @@ nil
=== TEST 9: compose: Compose key from parameters
--- http_config eval: $::HttpConfig
--- config
location =/t {
content_by_lua_block {
local p_384 = myassert(require("resty.openssl.pkey").new({
type = "EC",
"ec_paramgen_curve:secp384r1",
}))
local out = myassert(p_384:to_PEM('private'))
local params = p_384:get_parameters()
local newp_384, err = myassert(require("resty.openssl.pkey").new({
type = "EC",
params = {
private = params.private,
public = params.public,
group = params.group
}
}))
local out2 = myassert(newp_384:to_PEM('private'))
ngx.say(out == out2)
}
}
--- request
GET /t
--- response_body
true
--- no_error_log
[error]
=== TEST 9: paramgen: Outpus DH and EC params
--- http_config eval: $::HttpConfig
--- config
@ -883,7 +916,7 @@ pkey:verify: expect a string at #1
=== TEST 27: signature: Raw sign and recover
=== TEST 27: signature: Raw sign, raw verify and recover
--- http_config eval: $::HttpConfig
--- config
location =/t {
@ -895,6 +928,18 @@ pkey:verify: expect a string at #1
local v = myassert(p:verify_recover(s))
ngx.say(v == "🕶️")
local p = myassert(require("resty.openssl.pkey").new({
type = "EC",
curve = "prime256v1",
}))
local hashed = myassert(require("resty.openssl.digest").new("sha384"):final("🕶️"))
local s = myassert(p:sign_raw(hashed))
local v = myassert(p:verify_raw(s, hashed, "sha384"))
ngx.say(v == true)
}
}
--- request
@ -902,6 +947,7 @@ pkey:verify: expect a string at #1
--- response_body eval
"256
true
true
"
--- no_error_log
[error]