summaryrefslogtreecommitdiffstats
path: root/server/resty/openssl/x509/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/openssl/x509/init.lua')
-rw-r--r--server/resty/openssl/x509/init.lua1071
1 files changed, 1071 insertions, 0 deletions
diff --git a/server/resty/openssl/x509/init.lua b/server/resty/openssl/x509/init.lua
new file mode 100644
index 0000000..5c259c8
--- /dev/null
+++ b/server/resty/openssl/x509/init.lua
@@ -0,0 +1,1071 @@
+local ffi = require "ffi"
+local C = ffi.C
+local ffi_gc = ffi.gc
+local ffi_str = ffi.string
+local ffi_cast = ffi.cast
+
+require "resty.openssl.include.x509"
+require "resty.openssl.include.x509v3"
+require "resty.openssl.include.evp"
+require "resty.openssl.include.objects"
+local stack_macro = require("resty.openssl.include.stack")
+local stack_lib = require("resty.openssl.stack")
+local asn1_lib = require("resty.openssl.asn1")
+local digest_lib = require("resty.openssl.digest")
+local extension_lib = require("resty.openssl.x509.extension")
+local pkey_lib = require("resty.openssl.pkey")
+local bio_util = require "resty.openssl.auxiliary.bio"
+local txtnid2nid = require("resty.openssl.objects").txtnid2nid
+local find_sigid_algs = require("resty.openssl.objects").find_sigid_algs
+local ctypes = require "resty.openssl.auxiliary.ctypes"
+local ctx_lib = require "resty.openssl.ctx"
+local format_error = require("resty.openssl.err").format_error
+local version = require("resty.openssl.version")
+local OPENSSL_10 = version.OPENSSL_10
+local OPENSSL_11_OR_LATER = version.OPENSSL_11_OR_LATER
+local OPENSSL_3X = version.OPENSSL_3X
+local BORINGSSL = version.BORINGSSL
+local BORINGSSL_110 = version.BORINGSSL_110 -- used in boringssl-fips-20190808
+
+-- accessors provides an openssl version neutral interface to lua layer
+-- it doesn't handle any error, expect that to be implemented in
+-- _M.set_X or _M.get_X
+local accessors = {}
+
+accessors.get_pubkey = C.X509_get_pubkey -- returns new evp_pkey instance, don't need to dup
+accessors.set_pubkey = C.X509_set_pubkey
+accessors.set_version = C.X509_set_version
+accessors.set_serial_number = C.X509_set_serialNumber
+accessors.get_subject_name = C.X509_get_subject_name -- returns internal ptr, we dup it
+accessors.set_subject_name = C.X509_set_subject_name
+accessors.get_issuer_name = C.X509_get_issuer_name -- returns internal ptr, we dup it
+accessors.set_issuer_name = C.X509_set_issuer_name
+accessors.get_signature_nid = C.X509_get_signature_nid
+
+-- generally, use get1 if we return a lua table wrapped ctx which doesn't support dup.
+-- in that case, a new struct is returned from C api, and we will handle gc.
+-- openssl will increment the reference count for returned ptr, and won't free it when
+-- parent struct is freed.
+-- otherwise, use get0, which returns an internal pointer, we don't need to free it up.
+-- it will be gone together with the parent struct.
+
+if BORINGSSL_110 then
+ accessors.get_not_before = C.X509_get0_notBefore -- returns internal ptr, we convert to number
+ accessors.set_not_before = C.X509_set_notBefore
+ accessors.get_not_after = C.X509_get0_notAfter -- returns internal ptr, we convert to number
+ accessors.set_not_after = C.X509_set_notAfter
+ accessors.get_version = function(x509)
+ if x509 == nil or x509.cert_info == nil or x509.cert_info.validity == nil then
+ return nil
+ end
+ return C.ASN1_INTEGER_get(x509.cert_info.version)
+ end
+ accessors.get_serial_number = C.X509_get_serialNumber -- returns internal ptr, we convert to bn
+elseif OPENSSL_11_OR_LATER then
+ accessors.get_not_before = C.X509_get0_notBefore -- returns internal ptr, we convert to number
+ accessors.set_not_before = C.X509_set1_notBefore
+ accessors.get_not_after = C.X509_get0_notAfter -- returns internal ptr, we convert to number
+ accessors.set_not_after = C.X509_set1_notAfter
+ accessors.get_version = C.X509_get_version -- returns int
+ accessors.get_serial_number = C.X509_get0_serialNumber -- returns internal ptr, we convert to bn
+elseif OPENSSL_10 then
+ accessors.get_not_before = function(x509)
+ if x509 == nil or x509.cert_info == nil or x509.cert_info.validity == nil then
+ return nil
+ end
+ return x509.cert_info.validity.notBefore
+ end
+ accessors.set_not_before = C.X509_set_notBefore
+ accessors.get_not_after = function(x509)
+ if x509 == nil or x509.cert_info == nil or x509.cert_info.validity == nil then
+ return nil
+ end
+ return x509.cert_info.validity.notAfter
+ end
+ accessors.set_not_after = C.X509_set_notAfter
+ accessors.get_version = function(x509)
+ if x509 == nil or x509.cert_info == nil or x509.cert_info.validity == nil then
+ return nil
+ end
+ return C.ASN1_INTEGER_get(x509.cert_info.version)
+ end
+ accessors.get_serial_number = C.X509_get_serialNumber -- returns internal ptr, we convert to bn
+end
+
+local function __tostring(self, fmt)
+ if not fmt or fmt == 'PEM' then
+ return bio_util.read_wrap(C.PEM_write_bio_X509, self.ctx)
+ elseif fmt == 'DER' then
+ return bio_util.read_wrap(C.i2d_X509_bio, self.ctx)
+ else
+ return nil, "x509:tostring: can only write PEM or DER format, not " .. fmt
+ end
+end
+
+local _M = {}
+local mt = { __index = _M, __tostring = __tostring }
+
+
+local x509_ptr_ct = ffi.typeof("X509*")
+
+-- only PEM format is supported for now
+function _M.new(cert, fmt, properties)
+ local ctx
+ if not cert then
+ -- routine for create a new cert
+ if OPENSSL_3X then
+ ctx = C.X509_new_ex(ctx_lib.get_libctx(), properties)
+ else
+ ctx = C.X509_new()
+ end
+ if ctx == nil then
+ return nil, format_error("x509.new")
+ end
+ ffi_gc(ctx, C.X509_free)
+
+ C.X509_gmtime_adj(accessors.get_not_before(ctx), 0)
+ C.X509_gmtime_adj(accessors.get_not_after(ctx), 0)
+ elseif type(cert) == "string" then
+ -- routine for load an existing cert
+ local bio = C.BIO_new_mem_buf(cert, #cert)
+ if bio == nil then
+ return nil, format_error("x509.new: BIO_new_mem_buf")
+ end
+
+ fmt = fmt or "*"
+ while true do -- luacheck: ignore 512 -- loop is executed at most once
+ if fmt == "PEM" or fmt == "*" then
+ ctx = C.PEM_read_bio_X509(bio, nil, nil, nil)
+ if ctx ~= nil then
+ break
+ elseif fmt == "*" then
+ -- BIO_reset; #define BIO_CTRL_RESET 1
+ local code = C.BIO_ctrl(bio, 1, 0, nil)
+ if code ~= 1 then
+ C.BIO_free(bio)
+ return nil, "x509.new: BIO_ctrl() failed: " .. code
+ end
+ end
+ end
+ if fmt == "DER" or fmt == "*" then
+ ctx = C.d2i_X509_bio(bio, nil)
+ end
+ break
+ end
+ C.BIO_free(bio)
+ if ctx == nil then
+ return nil, format_error("x509.new")
+ end
+ -- clear errors occur when trying
+ C.ERR_clear_error()
+ ffi_gc(ctx, C.X509_free)
+ elseif type(cert) == 'cdata' then
+ if ffi.istype(x509_ptr_ct, cert) then
+ ctx = cert
+ ffi_gc(ctx, C.X509_free)
+ else
+ return nil, "x509.new: expect a X509* cdata at #1"
+ end
+ else
+ return nil, "x509.new: expect nil or a string at #1"
+ end
+
+ local self = setmetatable({
+ ctx = ctx,
+ }, mt)
+
+ return self, nil
+end
+
+function _M.istype(l)
+ return l and l.ctx and ffi.istype(x509_ptr_ct, l.ctx)
+end
+
+function _M.dup(ctx)
+ if not ffi.istype(x509_ptr_ct, ctx) then
+ return nil, "x509.dup: expect a x509 ctx at #1"
+ end
+ local ctx = C.X509_dup(ctx)
+ if ctx == nil then
+ return nil, "x509.dup: X509_dup() failed"
+ end
+
+ ffi_gc(ctx, C.X509_free)
+
+ local self = setmetatable({
+ ctx = ctx,
+ }, mt)
+
+ return self, nil
+end
+
+function _M:tostring(fmt)
+ return __tostring(self, fmt)
+end
+
+function _M:to_PEM()
+ return __tostring(self, "PEM")
+end
+
+function _M:set_lifetime(not_before, not_after)
+ local ok, err
+ if not_before then
+ ok, err = self:set_not_before(not_before)
+ if err then
+ return ok, err
+ end
+ end
+
+ if not_after then
+ ok, err = self:set_not_after(not_after)
+ if err then
+ return ok, err
+ end
+ end
+
+ return true
+end
+
+function _M:get_lifetime()
+ local not_before, err = self:get_not_before()
+ if not_before == nil then
+ return nil, nil, err
+ end
+ local not_after, err = self:get_not_after()
+ if not_after == nil then
+ return nil, nil, err
+ end
+
+ return not_before, not_after, nil
+end
+
+-- note: index is 0 based
+local OPENSSL_STRING_value_at = function(ctx, i)
+ local ct = ffi_cast("OPENSSL_STRING", stack_macro.OPENSSL_sk_value(ctx, i))
+ if ct == nil then
+ return nil
+ end
+ return ffi_str(ct)
+end
+
+function _M:get_ocsp_url(return_all)
+ local st = C.X509_get1_ocsp(self.ctx)
+
+ local count = stack_macro.OPENSSL_sk_num(st)
+ if count == 0 then
+ return
+ end
+
+ local ret
+ if return_all then
+ ret = {}
+ for i=0,count-1 do
+ ret[i+1] = OPENSSL_STRING_value_at(st, i)
+ end
+ else
+ ret = OPENSSL_STRING_value_at(st, 0)
+ end
+
+ C.X509_email_free(st)
+ return ret
+end
+
+function _M:get_ocsp_request()
+
+end
+
+function _M:get_crl_url(return_all)
+ local cdp, err = self:get_crl_distribution_points()
+ if err then
+ return nil, err
+ end
+
+ if not cdp or cdp:count() == 0 then
+ return
+ end
+
+ if return_all then
+ local ret = {}
+ local cdp_iter = cdp:each()
+ while true do
+ local _, gn = cdp_iter()
+ if not gn then
+ break
+ end
+ local gn_iter = gn:each()
+ while true do
+ local k, v = gn_iter()
+ if not k then
+ break
+ elseif k == "URI" then
+ table.insert(ret, v)
+ end
+ end
+ end
+ return ret
+ else
+ local gn, err = cdp:index(1)
+ if err then
+ return nil, err
+ end
+ local iter = gn:each()
+ while true do
+ local k, v = iter()
+ if not k then
+ break
+ elseif k == "URI" then
+ return v
+ end
+ end
+ end
+end
+
+local digest_length = ctypes.ptr_of_uint()
+local digest_buf, digest_buf_size
+local function digest(self, cfunc, typ, properties)
+ -- TODO: dedup the following with resty.openssl.digest
+ local ctx
+ if OPENSSL_11_OR_LATER then
+ ctx = C.EVP_MD_CTX_new()
+ ffi_gc(ctx, C.EVP_MD_CTX_free)
+ elseif OPENSSL_10 then
+ ctx = C.EVP_MD_CTX_create()
+ ffi_gc(ctx, C.EVP_MD_CTX_destroy)
+ end
+ if ctx == nil then
+ return nil, "x509:digest: failed to create EVP_MD_CTX"
+ end
+
+ local algo
+ if OPENSSL_3X then
+ algo = C.EVP_MD_fetch(ctx_lib.get_libctx(), typ or 'sha1', properties)
+ else
+ algo = C.EVP_get_digestbyname(typ or 'sha1')
+ end
+ if algo == nil then
+ return nil, string.format("x509:digest: invalid digest type \"%s\"", typ)
+ end
+
+ local md_size = OPENSSL_3X and C.EVP_MD_get_size(algo) or C.EVP_MD_size(algo)
+ if not digest_buf or digest_buf_size < md_size then
+ digest_buf = ctypes.uchar_array(md_size)
+ digest_buf_size = md_size
+ end
+
+ if cfunc(self.ctx, algo, digest_buf, digest_length) ~= 1 then
+ return nil, format_error("x509:digest")
+ end
+
+ return ffi_str(digest_buf, digest_length[0])
+end
+
+function _M:digest(typ, properties)
+ return digest(self, C.X509_digest, typ, properties)
+end
+
+function _M:pubkey_digest(typ, properties)
+ return digest(self, C.X509_pubkey_digest, typ, properties)
+end
+
+function _M:check_private_key(key)
+ if not pkey_lib.istype(key) then
+ return false, "x509:check_private_key: except a pkey instance at #1"
+ end
+
+ if not key:is_private() then
+ return false, "x509:check_private_key: not a private key"
+ end
+
+ if C.X509_check_private_key(self.ctx, key.ctx) == 1 then
+ return true
+ end
+ return false, format_error("x509:check_private_key")
+end
+
+-- START AUTO GENERATED CODE
+
+-- AUTO GENERATED
+function _M:sign(pkey, digest)
+ if not pkey_lib.istype(pkey) then
+ return false, "x509:sign: expect a pkey instance at #1"
+ end
+
+ local digest_algo
+ if digest then
+ if not digest_lib.istype(digest) then
+ return false, "x509:sign: expect a digest instance at #2"
+ elseif not digest.algo then
+ return false, "x509:sign: expect a digest instance to have algo member"
+ end
+ digest_algo = digest.algo
+ elseif BORINGSSL then
+ digest_algo = C.EVP_get_digestbyname('sha256')
+ end
+
+ -- returns size of signature if success
+ if C.X509_sign(self.ctx, pkey.ctx, digest_algo) == 0 then
+ return false, format_error("x509:sign")
+ end
+
+ return true
+end
+
+-- AUTO GENERATED
+function _M:verify(pkey)
+ if not pkey_lib.istype(pkey) then
+ return false, "x509:verify: expect a pkey instance at #1"
+ end
+
+ local code = C.X509_verify(self.ctx, pkey.ctx)
+ if code == 1 then
+ return true
+ elseif code == 0 then
+ return false
+ else -- typically -1
+ return false, format_error("x509:verify", code)
+ end
+end
+
+-- AUTO GENERATED
+local function get_extension(ctx, nid_txt, last_pos)
+ last_pos = (last_pos or 0) - 1
+ local nid, err = txtnid2nid(nid_txt)
+ if err then
+ return nil, nil, err
+ end
+ local pos = C.X509_get_ext_by_NID(ctx, nid, last_pos)
+ if pos == -1 then
+ return nil
+ end
+ local ctx = C.X509_get_ext(ctx, pos)
+ if ctx == nil then
+ return nil, nil, format_error()
+ end
+ return ctx, pos
+end
+
+-- AUTO GENERATED
+function _M:add_extension(extension)
+ if not extension_lib.istype(extension) then
+ return false, "x509:add_extension: expect a x509.extension instance at #1"
+ end
+
+ -- X509_add_ext returnes the stack on success, and NULL on error
+ -- the X509_EXTENSION ctx is dupped internally
+ if C.X509_add_ext(self.ctx, extension.ctx, -1) == nil then
+ return false, format_error("x509:add_extension")
+ end
+
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_extension(nid_txt, last_pos)
+ local ctx, pos, err = get_extension(self.ctx, nid_txt, last_pos)
+ if err then
+ return nil, nil, "x509:get_extension: " .. err
+ end
+ local ext, err = extension_lib.dup(ctx)
+ if err then
+ return nil, nil, "x509:get_extension: " .. err
+ end
+ return ext, pos+1
+end
+
+local X509_delete_ext
+if OPENSSL_11_OR_LATER then
+ X509_delete_ext = C.X509_delete_ext
+elseif OPENSSL_10 then
+ X509_delete_ext = function(ctx, pos)
+ return C.X509v3_delete_ext(ctx.cert_info.extensions, pos)
+ end
+else
+ X509_delete_ext = function(...)
+ error("X509_delete_ext undefined")
+ end
+end
+
+-- AUTO GENERATED
+function _M:set_extension(extension, last_pos)
+ if not extension_lib.istype(extension) then
+ return false, "x509:set_extension: expect a x509.extension instance at #1"
+ end
+
+ last_pos = (last_pos or 0) - 1
+
+ local nid = extension:get_object().nid
+ local pos = C.X509_get_ext_by_NID(self.ctx, nid, last_pos)
+ -- pos may be -1, which means not found, it's fine, we will add new one instead of replace
+
+ local removed = X509_delete_ext(self.ctx, pos)
+ C.X509_EXTENSION_free(removed)
+
+ if C.X509_add_ext(self.ctx, extension.ctx, pos) == nil then
+ return false, format_error("x509:set_extension")
+ end
+
+ return true
+end
+
+-- AUTO GENERATED
+function _M:set_extension_critical(nid_txt, crit, last_pos)
+ local ctx, _, err = get_extension(self.ctx, nid_txt, last_pos)
+ if err then
+ return nil, "x509:set_extension_critical: " .. err
+ end
+
+ if C.X509_EXTENSION_set_critical(ctx, crit and 1 or 0) ~= 1 then
+ return false, format_error("x509:set_extension_critical")
+ end
+
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_extension_critical(nid_txt, last_pos)
+ local ctx, _, err = get_extension(self.ctx, nid_txt, last_pos)
+ if err then
+ return nil, "x509:get_extension_critical: " .. err
+ end
+
+ return C.X509_EXTENSION_get_critical(ctx) == 1
+end
+
+-- AUTO GENERATED
+function _M:get_serial_number()
+ local got = accessors.get_serial_number(self.ctx)
+ if got == nil then
+ return nil
+ end
+
+ -- returns a new BIGNUM instance
+ got = C.ASN1_INTEGER_to_BN(got, nil)
+ if got == nil then
+ return false, format_error("x509:set: BN_to_ASN1_INTEGER")
+ end
+ -- bn will be duplicated thus this ctx should be freed up
+ ffi_gc(got, C.BN_free)
+
+ local lib = require("resty.openssl.bn")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED
+function _M:set_serial_number(toset)
+ local lib = require("resty.openssl.bn")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_serial_number: expect a bn instance at #1"
+ end
+ toset = toset.ctx
+
+ toset = C.BN_to_ASN1_INTEGER(toset, nil)
+ if toset == nil then
+ return false, format_error("x509:set: BN_to_ASN1_INTEGER")
+ end
+ -- "A copy of the serial number is used internally
+ -- so serial should be freed up after use.""
+ ffi_gc(toset, C.ASN1_INTEGER_free)
+
+ if accessors.set_serial_number(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_serial_number")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_not_before()
+ local got = accessors.get_not_before(self.ctx)
+ if got == nil then
+ return nil
+ end
+
+ got = asn1_lib.asn1_to_unix(got)
+
+ return got
+end
+
+-- AUTO GENERATED
+function _M:set_not_before(toset)
+ if type(toset) ~= "number" then
+ return false, "x509:set_not_before: expect a number at #1"
+ end
+
+ toset = C.ASN1_TIME_set(nil, toset)
+ ffi_gc(toset, C.ASN1_STRING_free)
+
+ if accessors.set_not_before(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_not_before")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_not_after()
+ local got = accessors.get_not_after(self.ctx)
+ if got == nil then
+ return nil
+ end
+
+ got = asn1_lib.asn1_to_unix(got)
+
+ return got
+end
+
+-- AUTO GENERATED
+function _M:set_not_after(toset)
+ if type(toset) ~= "number" then
+ return false, "x509:set_not_after: expect a number at #1"
+ end
+
+ toset = C.ASN1_TIME_set(nil, toset)
+ ffi_gc(toset, C.ASN1_STRING_free)
+
+ if accessors.set_not_after(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_not_after")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_pubkey()
+ local got = accessors.get_pubkey(self.ctx)
+ if got == nil then
+ return nil
+ end
+ local lib = require("resty.openssl.pkey")
+ -- returned a copied instance directly
+ return lib.new(got)
+end
+
+-- AUTO GENERATED
+function _M:set_pubkey(toset)
+ local lib = require("resty.openssl.pkey")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_pubkey: expect a pkey instance at #1"
+ end
+ toset = toset.ctx
+ if accessors.set_pubkey(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_pubkey")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_subject_name()
+ local got = accessors.get_subject_name(self.ctx)
+ if got == nil then
+ return nil
+ end
+ local lib = require("resty.openssl.x509.name")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED
+function _M:set_subject_name(toset)
+ local lib = require("resty.openssl.x509.name")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_subject_name: expect a x509.name instance at #1"
+ end
+ toset = toset.ctx
+ if accessors.set_subject_name(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_subject_name")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_issuer_name()
+ local got = accessors.get_issuer_name(self.ctx)
+ if got == nil then
+ return nil
+ end
+ local lib = require("resty.openssl.x509.name")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED
+function _M:set_issuer_name(toset)
+ local lib = require("resty.openssl.x509.name")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_issuer_name: expect a x509.name instance at #1"
+ end
+ toset = toset.ctx
+ if accessors.set_issuer_name(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_issuer_name")
+ end
+ return true
+end
+
+-- AUTO GENERATED
+function _M:get_version()
+ local got = accessors.get_version(self.ctx)
+ if got == nil then
+ return nil
+ end
+
+ got = tonumber(got) + 1
+
+ return got
+end
+
+-- AUTO GENERATED
+function _M:set_version(toset)
+ if type(toset) ~= "number" then
+ return false, "x509:set_version: expect a number at #1"
+ end
+
+ -- Note: this is defined by standards (X.509 et al) to be one less than the certificate version.
+ -- So a version 3 certificate will return 2 and a version 1 certificate will return 0.
+ toset = toset - 1
+
+ if accessors.set_version(self.ctx, toset) == 0 then
+ return false, format_error("x509:set_version")
+ end
+ return true
+end
+
+local NID_subject_alt_name = C.OBJ_sn2nid("subjectAltName")
+assert(NID_subject_alt_name ~= 0)
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_subject_alt_name()
+ local crit = ctypes.ptr_of_int()
+ -- X509_get_ext_d2i returns internal pointer, always dup
+ -- for now this function always returns the first found extension
+ local got = C.X509_get_ext_d2i(self.ctx, NID_subject_alt_name, crit, nil)
+ crit = tonumber(crit[0])
+ if crit == -1 then -- not found
+ return nil
+ elseif crit == -2 then
+ return nil, "x509:get_subject_alt_name: extension of subject_alt_name occurs more than one times, " ..
+ "this is not yet implemented. Please use get_extension instead."
+ elseif got == nil then
+ return nil, format_error("x509:get_subject_alt_name")
+ end
+
+ -- Note: here we only free the stack itself not elements
+ -- since there seems no way to increase ref count for a GENERAL_NAME
+ -- we left the elements referenced by the new-dup'ed stack
+ local got_ref = got
+ ffi_gc(got_ref, stack_lib.gc_of("GENERAL_NAME"))
+ got = ffi_cast("GENERAL_NAMES*", got_ref)
+ local lib = require("resty.openssl.x509.altname")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_subject_alt_name(toset)
+ local lib = require("resty.openssl.x509.altname")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_subject_alt_name: expect a x509.altname instance at #1"
+ end
+ toset = toset.ctx
+ -- x509v3.h: # define X509V3_ADD_REPLACE 2L
+ if C.X509_add1_ext_i2d(self.ctx, NID_subject_alt_name, toset, 0, 0x2) ~= 1 then
+ return false, format_error("x509:set_subject_alt_name")
+ end
+ return true
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_subject_alt_name_critical(crit)
+ return _M.set_extension_critical(self, NID_subject_alt_name, crit)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_subject_alt_name_critical()
+ return _M.get_extension_critical(self, NID_subject_alt_name)
+end
+
+local NID_issuer_alt_name = C.OBJ_sn2nid("issuerAltName")
+assert(NID_issuer_alt_name ~= 0)
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_issuer_alt_name()
+ local crit = ctypes.ptr_of_int()
+ -- X509_get_ext_d2i returns internal pointer, always dup
+ -- for now this function always returns the first found extension
+ local got = C.X509_get_ext_d2i(self.ctx, NID_issuer_alt_name, crit, nil)
+ crit = tonumber(crit[0])
+ if crit == -1 then -- not found
+ return nil
+ elseif crit == -2 then
+ return nil, "x509:get_issuer_alt_name: extension of issuer_alt_name occurs more than one times, " ..
+ "this is not yet implemented. Please use get_extension instead."
+ elseif got == nil then
+ return nil, format_error("x509:get_issuer_alt_name")
+ end
+
+ -- Note: here we only free the stack itself not elements
+ -- since there seems no way to increase ref count for a GENERAL_NAME
+ -- we left the elements referenced by the new-dup'ed stack
+ local got_ref = got
+ ffi_gc(got_ref, stack_lib.gc_of("GENERAL_NAME"))
+ got = ffi_cast("GENERAL_NAMES*", got_ref)
+ local lib = require("resty.openssl.x509.altname")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_issuer_alt_name(toset)
+ local lib = require("resty.openssl.x509.altname")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_issuer_alt_name: expect a x509.altname instance at #1"
+ end
+ toset = toset.ctx
+ -- x509v3.h: # define X509V3_ADD_REPLACE 2L
+ if C.X509_add1_ext_i2d(self.ctx, NID_issuer_alt_name, toset, 0, 0x2) ~= 1 then
+ return false, format_error("x509:set_issuer_alt_name")
+ end
+ return true
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_issuer_alt_name_critical(crit)
+ return _M.set_extension_critical(self, NID_issuer_alt_name, crit)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_issuer_alt_name_critical()
+ return _M.get_extension_critical(self, NID_issuer_alt_name)
+end
+
+local NID_basic_constraints = C.OBJ_sn2nid("basicConstraints")
+assert(NID_basic_constraints ~= 0)
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_basic_constraints(name)
+ local crit = ctypes.ptr_of_int()
+ -- X509_get_ext_d2i returns internal pointer, always dup
+ -- for now this function always returns the first found extension
+ local got = C.X509_get_ext_d2i(self.ctx, NID_basic_constraints, crit, nil)
+ crit = tonumber(crit[0])
+ if crit == -1 then -- not found
+ return nil
+ elseif crit == -2 then
+ return nil, "x509:get_basic_constraints: extension of basic_constraints occurs more than one times, " ..
+ "this is not yet implemented. Please use get_extension instead."
+ elseif got == nil then
+ return nil, format_error("x509:get_basic_constraints")
+ end
+
+ local ctx = ffi_cast("BASIC_CONSTRAINTS*", got)
+
+ local ca = ctx.ca == 0xFF
+ local pathlen = tonumber(C.ASN1_INTEGER_get(ctx.pathlen))
+
+ C.BASIC_CONSTRAINTS_free(ctx)
+
+ if not name or type(name) ~= "string" then
+ got = {
+ ca = ca,
+ pathlen = pathlen,
+ }
+ elseif string.lower(name) == "ca" then
+ got = ca
+ elseif string.lower(name) == "pathlen" then
+ got = pathlen
+ end
+
+ return got
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_basic_constraints(toset)
+ if type(toset) ~= "table" then
+ return false, "x509:set_basic_constraints: expect a table at #1"
+ end
+
+ local cfg_lower = {}
+ for k, v in pairs(toset) do
+ cfg_lower[string.lower(k)] = v
+ end
+
+ toset = C.BASIC_CONSTRAINTS_new()
+ if toset == nil then
+ return false, format_error("x509:set_BASIC_CONSTRAINTS")
+ end
+ ffi_gc(toset, C.BASIC_CONSTRAINTS_free)
+
+ toset.ca = cfg_lower.ca and 0xFF or 0
+ local pathlen = cfg_lower.pathlen and tonumber(cfg_lower.pathlen)
+ if pathlen then
+ C.ASN1_INTEGER_free(toset.pathlen)
+
+ local asn1 = C.ASN1_STRING_type_new(pathlen)
+ if asn1 == nil then
+ return false, format_error("x509:set_BASIC_CONSTRAINTS: ASN1_STRING_type_new")
+ end
+ toset.pathlen = asn1
+
+ local code = C.ASN1_INTEGER_set(asn1, pathlen)
+ if code ~= 1 then
+ return false, format_error("x509:set_BASIC_CONSTRAINTS: ASN1_INTEGER_set", code)
+ end
+ end
+
+ -- x509v3.h: # define X509V3_ADD_REPLACE 2L
+ if C.X509_add1_ext_i2d(self.ctx, NID_basic_constraints, toset, 0, 0x2) ~= 1 then
+ return false, format_error("x509:set_basic_constraints")
+ end
+ return true
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_basic_constraints_critical(crit)
+ return _M.set_extension_critical(self, NID_basic_constraints, crit)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_basic_constraints_critical()
+ return _M.get_extension_critical(self, NID_basic_constraints)
+end
+
+local NID_info_access = C.OBJ_sn2nid("authorityInfoAccess")
+assert(NID_info_access ~= 0)
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_info_access()
+ local crit = ctypes.ptr_of_int()
+ -- X509_get_ext_d2i returns internal pointer, always dup
+ -- for now this function always returns the first found extension
+ local got = C.X509_get_ext_d2i(self.ctx, NID_info_access, crit, nil)
+ crit = tonumber(crit[0])
+ if crit == -1 then -- not found
+ return nil
+ elseif crit == -2 then
+ return nil, "x509:get_info_access: extension of info_access occurs more than one times, " ..
+ "this is not yet implemented. Please use get_extension instead."
+ elseif got == nil then
+ return nil, format_error("x509:get_info_access")
+ end
+
+ -- Note: here we only free the stack itself not elements
+ -- since there seems no way to increase ref count for a ACCESS_DESCRIPTION
+ -- we left the elements referenced by the new-dup'ed stack
+ local got_ref = got
+ ffi_gc(got_ref, stack_lib.gc_of("ACCESS_DESCRIPTION"))
+ got = ffi_cast("AUTHORITY_INFO_ACCESS*", got_ref)
+ local lib = require("resty.openssl.x509.extension.info_access")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_info_access(toset)
+ local lib = require("resty.openssl.x509.extension.info_access")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_info_access: expect a x509.extension.info_access instance at #1"
+ end
+ toset = toset.ctx
+ -- x509v3.h: # define X509V3_ADD_REPLACE 2L
+ if C.X509_add1_ext_i2d(self.ctx, NID_info_access, toset, 0, 0x2) ~= 1 then
+ return false, format_error("x509:set_info_access")
+ end
+ return true
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_info_access_critical(crit)
+ return _M.set_extension_critical(self, NID_info_access, crit)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_info_access_critical()
+ return _M.get_extension_critical(self, NID_info_access)
+end
+
+local NID_crl_distribution_points = C.OBJ_sn2nid("crlDistributionPoints")
+assert(NID_crl_distribution_points ~= 0)
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_crl_distribution_points()
+ local crit = ctypes.ptr_of_int()
+ -- X509_get_ext_d2i returns internal pointer, always dup
+ -- for now this function always returns the first found extension
+ local got = C.X509_get_ext_d2i(self.ctx, NID_crl_distribution_points, crit, nil)
+ crit = tonumber(crit[0])
+ if crit == -1 then -- not found
+ return nil
+ elseif crit == -2 then
+ return nil, "x509:get_crl_distribution_points: extension of crl_distribution_points occurs more than one times, " ..
+ "this is not yet implemented. Please use get_extension instead."
+ elseif got == nil then
+ return nil, format_error("x509:get_crl_distribution_points")
+ end
+
+ -- Note: here we only free the stack itself not elements
+ -- since there seems no way to increase ref count for a DIST_POINT
+ -- we left the elements referenced by the new-dup'ed stack
+ local got_ref = got
+ ffi_gc(got_ref, stack_lib.gc_of("DIST_POINT"))
+ got = ffi_cast("OPENSSL_STACK*", got_ref)
+ local lib = require("resty.openssl.x509.extension.dist_points")
+ -- the internal ptr is returned, ie we need to copy it
+ return lib.dup(got)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_crl_distribution_points(toset)
+ local lib = require("resty.openssl.x509.extension.dist_points")
+ if lib.istype and not lib.istype(toset) then
+ return false, "x509:set_crl_distribution_points: expect a x509.extension.dist_points instance at #1"
+ end
+ toset = toset.ctx
+ -- x509v3.h: # define X509V3_ADD_REPLACE 2L
+ if C.X509_add1_ext_i2d(self.ctx, NID_crl_distribution_points, toset, 0, 0x2) ~= 1 then
+ return false, format_error("x509:set_crl_distribution_points")
+ end
+ return true
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:set_crl_distribution_points_critical(crit)
+ return _M.set_extension_critical(self, NID_crl_distribution_points, crit)
+end
+
+-- AUTO GENERATED: EXTENSIONS
+function _M:get_crl_distribution_points_critical()
+ return _M.get_extension_critical(self, NID_crl_distribution_points)
+end
+
+
+-- AUTO GENERATED
+function _M:get_signature_nid()
+ local nid = accessors.get_signature_nid(self.ctx)
+ if nid <= 0 then
+ return nil, format_error("x509:get_signature_nid")
+ end
+
+ return nid
+end
+
+-- AUTO GENERATED
+function _M:get_signature_name()
+ local nid = accessors.get_signature_nid(self.ctx)
+ if nid <= 0 then
+ return nil, format_error("x509:get_signature_name")
+ end
+
+ return ffi.string(C.OBJ_nid2sn(nid))
+end
+
+-- AUTO GENERATED
+function _M:get_signature_digest_name()
+ local nid = accessors.get_signature_nid(self.ctx)
+ if nid <= 0 then
+ return nil, format_error("x509:get_signature_digest_name")
+ end
+
+ local nid = find_sigid_algs(nid)
+
+ return ffi.string(C.OBJ_nid2sn(nid))
+end
+-- END AUTO GENERATED CODE
+
+return _M