summaryrefslogtreecommitdiffstats
path: root/server/resty/openssl/provider.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/openssl/provider.lua')
-rw-r--r--server/resty/openssl/provider.lua136
1 files changed, 136 insertions, 0 deletions
diff --git a/server/resty/openssl/provider.lua b/server/resty/openssl/provider.lua
new file mode 100644
index 0000000..2879ac3
--- /dev/null
+++ b/server/resty/openssl/provider.lua
@@ -0,0 +1,136 @@
+local ffi = require "ffi"
+local C = ffi.C
+
+require "resty.openssl.include.provider"
+local param_lib = require "resty.openssl.param"
+local ctx_lib = require "resty.openssl.ctx"
+local null = require("resty.openssl.auxiliary.ctypes").null
+local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X
+local format_error = require("resty.openssl.err").format_error
+
+if not OPENSSL_3X then
+ error("provider is only supported since OpenSSL 3.0")
+end
+
+local _M = {}
+local mt = {__index = _M}
+
+local ossl_provider_ctx_ct = ffi.typeof('OSSL_PROVIDER*')
+
+function _M.load(name, try)
+ local ctx
+ local libctx = ctx_lib.get_libctx()
+ if try then
+ ctx = C.OSSL_PROVIDER_try_load(libctx, name)
+ if ctx == nil then
+ return nil, format_error("provider.try_load")
+ end
+ else
+ ctx = C.OSSL_PROVIDER_load(libctx, name)
+ if ctx == nil then
+ return nil, format_error("provider.load")
+ end
+ end
+
+ return setmetatable({
+ ctx = ctx,
+ param_types = nil,
+ }, mt), nil
+end
+
+function _M.set_default_search_path(path)
+ C.OSSL_PROVIDER_set_default_search_path(ctx_lib.get_libctx(), path)
+end
+
+function _M.is_available(name)
+ return C.OSSL_PROVIDER_available(ctx_lib.get_libctx(), name) == 1
+end
+
+function _M.istype(l)
+ return l and l.ctx and ffi.istype(ossl_provider_ctx_ct, l.ctx)
+end
+
+function _M:unload()
+ if C.OSSL_PROVIDER_unload(self.ctx) == nil then
+ return false, format_error("provider:unload")
+ end
+ return true
+end
+
+function _M:self_test()
+ if C.OSSL_PROVIDER_self_test(self.ctx) == nil then
+ return false, format_error("provider:self_test")
+ end
+ return true
+end
+
+local params_well_known = {
+ -- Well known parameter names that core passes to providers
+ ["openssl-version"] = param_lib.OSSL_PARAM_UTF8_PTR,
+ ["provider-name"] = param_lib.OSSL_PARAM_UTF8_PTR,
+ ["module-filename"] = param_lib.OSSL_PARAM_UTF8_PTR,
+
+ -- Well known parameter names that Providers can define
+ ["name"] = param_lib.OSSL_PARAM_UTF8_PTR,
+ ["version"] = param_lib.OSSL_PARAM_UTF8_PTR,
+ ["buildinfo"] = param_lib.OSSL_PARAM_UTF8_PTR,
+ ["status"] = param_lib.OSSL_PARAM_INTEGER,
+ ["security-checks"] = param_lib.OSSL_PARAM_INTEGER,
+}
+
+local function load_gettable_names(ctx)
+ local schema = {}
+ for k, v in pairs(params_well_known) do
+ schema[k] = v
+ end
+
+ local err
+ schema, err = param_lib.parse_params_schema(
+ C.OSSL_PROVIDER_gettable_params(ctx), schema)
+ if err then
+ return nil, err
+ end
+
+ return schema
+end
+
+function _M:get_params(...)
+ local keys = {...}
+ local key_length = #keys
+ if key_length == 0 then
+ return nil, "provider:get_params: at least one key is required"
+ end
+
+ if not self.param_types then
+ local param_types, err = load_gettable_names(self.ctx)
+ if err then
+ return nil, "provider:get_params: " .. err
+ end
+ self.param_types = param_types
+ end
+
+ local buffers = {}
+ for _, key in ipairs(keys) do
+ buffers[key] = null
+ end
+ local req, err = param_lib.construct(buffers, key_length, self.param_types)
+ if not req then
+ return nil, "provider:get_params: failed to construct params: " .. err
+ end
+
+ if C.OSSL_PROVIDER_get_params(self.ctx, req) ~= 1 then
+ return nil, format_error("provider:get_params")
+ end
+
+ buffers, err = param_lib.parse(buffers, key_length, self.param_types)
+ if err then
+ return nil, "provider:get_params: failed to parse params: " .. err
+ end
+
+ if key_length == 1 then
+ return buffers[keys[1]]
+ end
+ return buffers
+end
+
+return _M