├── .chglog ├── CHANGELOG.tpl.md └── config.yml ├── .editorconfig ├── .github └── workflows │ ├── lint.yml │ └── tests.yml ├── .gitignore ├── .luacheckrc ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── dist.ini ├── examples ├── aes-gcm-aead.lua ├── csr.lua ├── info.lua ├── perf │ ├── framework.lua │ ├── test_cipher.lua │ ├── test_other_libs.lua │ ├── test_pkey_asymm.lua │ ├── test_pkey_codec.lua │ └── test_x509_codec.lua ├── raw-sign-and-recover.lua ├── self-signed.lua ├── tls-alpn-01.lua └── x25519-dh.lua ├── lib └── resty │ ├── openssl.lua │ └── openssl │ ├── asn1.lua │ ├── auxiliary │ ├── bio.lua │ ├── compat.lua │ ├── ctypes.lua │ ├── ecdsa.lua │ ├── jwk.lua │ ├── nginx.lua │ └── nginx_c.lua │ ├── bn.lua │ ├── cipher.lua │ ├── ctx.lua │ ├── dh.lua │ ├── digest.lua │ ├── ec.lua │ ├── ecx.lua │ ├── err.lua │ ├── hmac.lua │ ├── include │ ├── asn1.lua │ ├── bio.lua │ ├── bn.lua │ ├── conf.lua │ ├── crypto.lua │ ├── dh.lua │ ├── ec.lua │ ├── ecdsa.lua │ ├── err.lua │ ├── evp.lua │ ├── evp │ │ ├── cipher.lua │ │ ├── kdf.lua │ │ ├── mac.lua │ │ ├── md.lua │ │ └── pkey.lua │ ├── hmac.lua │ ├── objects.lua │ ├── ossl_typ.lua │ ├── param.lua │ ├── pem.lua │ ├── pkcs12.lua │ ├── provider.lua │ ├── rand.lua │ ├── rsa.lua │ ├── ssl.lua │ ├── stack.lua │ ├── x509 │ │ ├── altname.lua │ │ ├── crl.lua │ │ ├── csr.lua │ │ ├── extension.lua │ │ ├── init.lua │ │ ├── name.lua │ │ └── revoked.lua │ ├── x509_vfy.lua │ └── x509v3.lua │ ├── kdf.lua │ ├── mac.lua │ ├── objects.lua │ ├── param.lua │ ├── pkcs12.lua │ ├── pkey.lua │ ├── provider.lua │ ├── rand.lua │ ├── rsa.lua │ ├── ssl.lua │ ├── ssl_ctx.lua │ ├── stack.lua │ ├── version.lua │ └── x509 │ ├── altname.lua │ ├── chain.lua │ ├── crl.lua │ ├── csr.lua │ ├── extension.lua │ ├── extension │ ├── dist_points.lua │ └── info_access.lua │ ├── extensions.lua │ ├── init.lua │ ├── name.lua │ ├── revoked.lua │ └── store.lua ├── lua-resty-openssl-1.6.1-1.rockspec ├── scripts ├── extension_struct.py ├── find_unused_cdef.py ├── opm_upload.sh ├── prepare_new_release.sh ├── requirements.txt ├── templates │ ├── x509_functions.j2 │ └── x509_tests.j2 ├── type_x509.py ├── type_x509_crl.py ├── type_x509_req.py ├── types_test.py └── x509_autogen.py ├── t ├── fips.t ├── fixtures │ ├── Github.pem │ ├── GlobalSign.pem │ ├── GlobalSign_sub.pem │ ├── TrustAsiaEVTLSProCAG2.crl │ ├── badssl.com-client.p12 │ ├── crl │ │ ├── crl.pem │ │ ├── gen_certs.sh │ │ ├── revoked.cert.pem │ │ ├── revoked.key.pem │ │ ├── rootca.cert.pem │ │ ├── rootca.cnf │ │ ├── rootca.key.pem │ │ ├── subca.cert.pem │ │ ├── subca.cnf │ │ ├── subca.key.pem │ │ ├── valid.cert.pem │ │ └── valid.key.pem │ ├── ec_key_encrypted.pem │ ├── no_revoked.crl │ ├── openssl_fips.cnf │ ├── rsa-pkcs1-priv.key │ ├── rsa-pkcs1-pub.key │ ├── test.crt │ ├── test.csr │ └── test.key ├── openssl.t └── openssl │ ├── asn1.t │ ├── aux │ └── jwk.t │ ├── bn.t │ ├── cipher.t │ ├── ctx.t │ ├── digest.t │ ├── err.t │ ├── helper.lua │ ├── hmac.t │ ├── kdf.t │ ├── mac.t │ ├── objects.t │ ├── param.t │ ├── pkcs12.t │ ├── pkey.t │ ├── provider.t │ ├── rand.t │ ├── ssl │ ├── ssl_client.t │ ├── ssl_ctx_server.t │ └── ssl_server.t │ ├── version.t │ ├── x509.t │ └── x509 │ ├── altname.t │ ├── chain.t │ ├── crl.t │ ├── csr.lua │ ├── csr.t │ ├── extension.t │ ├── extensions.t │ ├── name.t │ ├── revoked.t │ └── store.t └── valgrind.suppress /.chglog/CHANGELOG.tpl.md: -------------------------------------------------------------------------------- 1 | {{ if .Versions -}} 2 | 3 | ## [Unreleased] 4 | 5 | {{ if .Unreleased.CommitGroups -}} 6 | {{ range .Unreleased.CommitGroups -}} 7 | ### {{ .Title }} 8 | {{ range .Commits -}} 9 | - {{ if .Scope }}**{{ replace .Scope "*" "\\*" -1 }}:** {{ end }}{{ .Subject }} 10 | {{ end }} 11 | {{ end -}} 12 | {{ end -}} 13 | {{ end -}} 14 | 15 | {{ range .Versions }} 16 | 17 | ## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} 18 | {{ range .CommitGroups -}} 19 | ### {{ lower .Title }} 20 | {{ range .Commits -}} 21 | - {{ if .Scope }}**{{ replace .Scope "*" "\\*" -1 }}:** {{ end }}{{ .Subject }} [{{ .Hash.Short }}]({{ $.Info.RepositoryURL }}/commit/{{ .Hash.Long }}) 22 | {{ end }} 23 | {{ end -}} 24 | 25 | {{- if .NoteGroups -}} 26 | {{ range .NoteGroups -}} 27 | ### {{ .Title }} 28 | {{ range .Notes }} 29 | {{ .Body }} 30 | {{ end }} 31 | {{ end -}} 32 | {{ end -}} 33 | {{ end -}} 34 | 35 | {{- if .Versions }} 36 | [Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD 37 | {{ range .Versions -}} 38 | {{ if .Tag.Previous -}} 39 | [{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} 40 | {{ end -}} 41 | {{ end -}} 42 | {{ end -}} 43 | -------------------------------------------------------------------------------- /.chglog/config.yml: -------------------------------------------------------------------------------- 1 | style: github 2 | template: CHANGELOG.tpl.md 3 | info: 4 | title: CHANGELOG 5 | repository_url: https://github.com/fffonion/lua-resty-openssl 6 | options: 7 | sort: "semver" 8 | commits: 9 | filters: 10 | Type: 11 | - feat 12 | - fix 13 | - perf 14 | - refactor 15 | commit_groups: 16 | title_maps: 17 | feat: Features 18 | fix: Bug Fixes 19 | perf: Performance Improvements 20 | refactor: Code Refactoring 21 | header: 22 | pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s\\/]*)\\))?:?\\s(.*)$" 23 | pattern_maps: 24 | - Type 25 | - Scope 26 | - Subject 27 | notes: 28 | keywords: 29 | - BREAKING CHANGE 30 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | 9 | [*.lua] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [Makefile] 14 | indent_style = tab 15 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - lib/**.lua 7 | push: 8 | branches: 9 | - master 10 | - release/* 11 | paths: 12 | - lib/**.lua 13 | 14 | 15 | jobs: 16 | tests: 17 | name: Lint 18 | runs-on: ubuntu-22.04 19 | 20 | steps: 21 | - name: Checkout source code 22 | uses: actions/checkout@v2 23 | - uses: Jayrgo/luacheck-action@v1 24 | name: luacheck 25 | with: 26 | # List of files, directories and rockspecs to check. 27 | # Default: . 28 | files: 'lib' 29 | 30 | # Path to configuration file. 31 | # Default: .luacheckrc 32 | config: '.luacheckrc' 33 | 34 | # Arguments passed to luacheck. 35 | # Default: -q 36 | args: '-q' 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | t/servroot 2 | __pycache__ 3 | .idea/ -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | std = "ngx_lua" 2 | unused_args = false 3 | redefined = false 4 | max_line_length = false 5 | 6 | 7 | not_globals = { 8 | "string.len", 9 | "table.getn", 10 | } 11 | 12 | 13 | ignore = { 14 | "6.", -- ignore whitespace warnings 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Wangchong Zhou 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OPENRESTY_PREFIX=/usr/local/openresty 2 | 3 | #LUA_VERSION := 5.1 4 | PREFIX ?= /usr/local 5 | LUA_INCLUDE_DIR ?= $(PREFIX)/include 6 | LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) 7 | 8 | .PHONY: all test install 9 | 10 | all: ; 11 | 12 | install: all 13 | cp -rpv lib/resty/openssl/. $(DESTDIR)$(LUA_LIB_DIR)/resty/openssl 14 | cp -pv lib/resty/openssl.lua $(DESTDIR)$(LUA_LIB_DIR)/resty/ 15 | 16 | test: all 17 | PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH prove -I../test-nginx/lib -r t 18 | 19 | 20 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name = lua-resty-openssl 2 | abstract = FFI-based OpenSSL binding for LuaJIT 3 | author = fffonion 4 | is_original = yes 5 | license = 3bsd 6 | lib_dir = lib 7 | doc_dir = lib 8 | repo_link = https://github.com/fffonion/lua-resty-openssl 9 | main_module = lib/resty/openssl.lua 10 | requires = luajit 11 | exclude_files=*.rock, *.rockspec 12 | -------------------------------------------------------------------------------- /examples/aes-gcm-aead.lua: -------------------------------------------------------------------------------- 1 | local key = string.rep("0", 32) 2 | local iv = string.rep("0", 12) 3 | 4 | local to_be_encrypted = "secret" 5 | 6 | local aad = "aead aad" 7 | 8 | local mode = "aes-256-gcm" 9 | -- local mode = "chacha20-poly1305" 10 | ngx.say("use cipher ", mode) 11 | 12 | -- using one shot interface 13 | local cipher = assert(require("resty.openssl.cipher").new(mode)) 14 | local encrypted = assert(cipher:encrypt(key, iv, to_be_encrypted, false, aad)) 15 | -- OR using streaming interface 16 | assert(cipher:init(key, iv, { 17 | is_encrypt = true, 18 | })) 19 | assert(cipher:update_aead_aad(aad)) 20 | encrypted = assert(cipher:final(to_be_encrypted)) 21 | 22 | ngx.say("encryption result: ", ngx.encode_base64(encrypted)) 23 | 24 | local tag = assert(cipher:get_aead_tag()) 25 | 26 | ngx.say("tag is: ", ngx.encode_base64(tag), " ", #tag) 27 | 28 | local _, err = cipher:decrypt(key, iv, encrypted, false, nil, tag) 29 | if err then 30 | ngx.say("no AAD, decryption failed") 31 | end 32 | 33 | local _, err = cipher:decrypt(key, iv, encrypted, false, "wrong", tag) 34 | if err then 35 | ngx.say("wrong AAD, decryption failed") 36 | end 37 | 38 | -- this seems not working for chacha20-poly1305 39 | local _, err = cipher:decrypt(key, iv, encrypted, false, aad, nil) 40 | if err then 41 | ngx.say("no tag, decryption failed") 42 | end 43 | 44 | local _, err = cipher:decrypt(key, iv, encrypted, false, aad, "wrong") 45 | if err then 46 | ngx.say("wrong tag, decryption failed") 47 | end 48 | 49 | -- using one shot interface 50 | local decrypted = assert(cipher:decrypt(key, iv, encrypted, false, aad, tag)) 51 | -- OR using streaming interface 52 | assert(cipher:init(key, iv, { 53 | is_encrypt = false, 54 | })) 55 | assert(cipher:update_aead_aad(aad)) 56 | assert(cipher:set_aead_tag(tag)) 57 | decrypted = assert(cipher:final(encrypted)) 58 | 59 | ngx.say("decryption result: ", decrypted) 60 | 61 | --[[ 62 | Note in some implementations like `libsodium` or Java, AEAD ciphers append the `tag` (or `MAC`) 63 | at the end of encrypted ciphertext. In such case, user will need to manually cut off the `tag` 64 | with correct size(usually 16 bytes) and pass in the ciphertext and `tag` seperately. 65 | 66 | -- encrypt with libsodium and decrypt in lua-resty-openssl 67 | 68 | 76 | 77 | local tag = string.sub(encrypted_with_tag, #encrypted_with_tag-16, #encrypted_with_tag) 78 | local encrypted = string.sub(encrypted_with_tag, 1, #encrypted_with_tag-16) 79 | local decrypted = assert(cipher:decrypt(key, iv, encrypted, false, aad, tag)) 80 | 81 | 82 | -- encrypt with lua-resty-openssl and decrypt in libsodium 83 | 84 | local encrypted = assert(cipher:encrypt(key, iv, to_be_encrypted, false, aad)) 85 | local tag = assert(cipher:get_aead_tag()) 86 | 87 | 95 | 96 | ]]-- 97 | 98 | --[[ 99 | If the encryption is not done properly, it's possible that no tag is provided after all. 100 | In such case, use the streaming interface and call update() instead of final() 101 | ]] 102 | 103 | assert(cipher:init(key, iv, { 104 | is_encrypt = false, 105 | })) 106 | assert(cipher:update_aead_aad(aad)) 107 | decrypted = assert(cipher:update(encrypted)) 108 | 109 | ngx.say("decryption result (without checking MAC): ", decrypted) 110 | 111 | -------------------------------------------------------------------------------- /examples/csr.lua: -------------------------------------------------------------------------------- 1 | 2 | -- sample function to generate a DER CSR from given pkey and domains 3 | local function create_csr(domain_pkey, ...) 4 | local domains = {...} 5 | 6 | local subject = require("resty.openssl.x509.name").new() 7 | local _, err = subject:add("CN", domains[1]) 8 | if err then 9 | return nil, err 10 | end 11 | 12 | local alt, err 13 | if #{...} > 1 then 14 | alt, err = require("resty.openssl.x509.altname").new() 15 | if err then 16 | return nil, err 17 | end 18 | 19 | for _, domain in pairs(domains) do 20 | _, err = alt:add("DNS", domain) 21 | if err then 22 | return nil, err 23 | end 24 | end 25 | end 26 | 27 | local csr = require("resty.openssl.x509.csr").new() 28 | local _ 29 | _, err = csr:set_subject_name(subject) 30 | if err then 31 | return nil, err 32 | end 33 | 34 | if alt then 35 | _, err = csr:set_subject_alt_name(alt) 36 | if err then 37 | return nil, err 38 | end 39 | end 40 | 41 | _, err = csr:set_pubkey(domain_pkey) 42 | if err then 43 | return nil, err 44 | end 45 | 46 | _, err = csr:sign(domain_pkey) 47 | if err then 48 | return nil, err 49 | end 50 | 51 | return csr:tostring("DER"), nil 52 | end 53 | 54 | -- create a EC key 55 | local pkey, err = require("resty.openssl.pkey").new({ 56 | type = 'EC', 57 | curve = 'prime256v1', 58 | }) 59 | if err then 60 | error(err) 61 | end 62 | 63 | -- create a CSR using the key 64 | local der, err = create_csr(pkey, "example.com", "*.example.com") 65 | if err then 66 | error(err) 67 | end 68 | 69 | -- use openssl cli to see csr we just generated 70 | local f = io.open("example.csr", "w") 71 | f:write(der) 72 | f:close() 73 | os.execute("openssl req -in example.csr -inform der -noout -text") 74 | os.remove("example.csr") 75 | -------------------------------------------------------------------------------- /examples/info.lua: -------------------------------------------------------------------------------- 1 | local version=require "resty.openssl.version" 2 | 3 | print("VERSION:") 4 | 5 | local version_table = { 6 | "VERSION", 7 | "CFLAGS", 8 | "BUILT_ON", 9 | "PLATFORM", 10 | "DIR", 11 | "ENGINES_DIR", 12 | "VERSION_STRING", 13 | "FULL_VERSION_STRING", 14 | "MODULES_DIR", 15 | "CPU_INFO", 16 | } 17 | 18 | for _, k in ipairs(version_table) do 19 | print(string.format("%20s: %s", k, version.version(version[k]))) 20 | end 21 | 22 | print(string.rep("-", 64)) 23 | 24 | if version.OPENSSL_3X then 25 | 26 | print("INFO:") 27 | local info_table = { 28 | "INFO_CONFIG_DIR", 29 | "INFO_ENGINES_DIR", 30 | "INFO_MODULES_DIR", 31 | "INFO_DSO_EXTENSION", 32 | "INFO_DIR_FILENAME_SEPARATOR", 33 | "INFO_LIST_SEPARATOR", 34 | "INFO_SEED_SOURCE", 35 | "INFO_CPU_SETTINGS", 36 | } 37 | 38 | for _, k in ipairs(info_table) do 39 | print(string.format("%20s: %s", k, version.info(version[k]))) 40 | end 41 | 42 | print(string.rep("-", 64)) 43 | 44 | print("PROVIDER:") 45 | local pro = require "resty.openssl.provider" 46 | 47 | for _, n in ipairs({"default", "legacy", "fips", "null"}) do 48 | local ok, err = pro.load(n) 49 | print(string.format("%10s load: %s", n, ok or err)) 50 | end 51 | end 52 | 53 | -------------------------------------------------------------------------------- /examples/perf/framework.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ITER = 2000 4 | 5 | local get_duration 6 | do 7 | ffi.cdef [[ 8 | 9 | typedef long time_t; 10 | typedef int clockid_t; 11 | typedef struct timespec { 12 | time_t tv_sec; /* seconds */ 13 | long tv_nsec; /* nanoseconds */ 14 | } nanotime; 15 | 16 | int clock_gettime(clockid_t clk_id, struct timespec *tp); 17 | 18 | ]] 19 | local time_ns 20 | do 21 | local nanop = ffi.new("nanotime[1]") 22 | function time_ns() 23 | -- CLOCK_REALTIME -> 0 24 | C.clock_gettime(0, nanop) 25 | local t = nanop[0] 26 | 27 | return tonumber(t.tv_sec) * 1e9 + tonumber(t.tv_nsec) 28 | end 29 | end 30 | 31 | local last = 0 32 | get_duration = function() 33 | local n = time_ns() 34 | local d = n - last 35 | last = n 36 | return d 37 | end 38 | end 39 | 40 | local function hmt(t) 41 | if t > 1e9 * 0.01 then 42 | return string.format("%.3f s", t/1e9) 43 | elseif t > 1e6 * 0.01 then 44 | return string.format("%.3f ms", t/1e6) 45 | else 46 | return string.format("%d ns", t) 47 | end 48 | end 49 | 50 | -- return sum, avg, max 51 | local function stat(t) 52 | if not t then 53 | return 0, 0, 0 54 | end 55 | 56 | local v = 0 57 | local max = 0 58 | for _, i in ipairs(t) do 59 | v = v + i 60 | if i > max then 61 | max = i 62 | end 63 | end 64 | return v, v/#t, max 65 | end 66 | 67 | local write_seperator = function() 68 | print(string.rep("-", 64)) 69 | end 70 | 71 | local no_count_iter = false 72 | 73 | local run_only = os.getenv("RUN_ONLY") 74 | 75 | local function test(desc, r, iter, expected) 76 | if run_only and not string.match(desc, run_only) then 77 | print("SKIP " .. desc) 78 | return 79 | end 80 | 81 | print("RUNNING " .. ITER .. " ITERATIONS FOR " .. desc) 82 | local sum, avg, max 83 | local ok, err 84 | 85 | if no_count_iter then 86 | get_duration() 87 | for i=1, ITER do 88 | ok, err = r() 89 | end 90 | local duration = get_duration() 91 | assert(ok, err) 92 | sum, avg, max = duration, duration/ITER, 1/0 93 | else 94 | local data = table.new(ITER, 0) 95 | for i=1, ITER do 96 | get_duration() 97 | ok, err = r() 98 | data[i] = get_duration() 99 | assert(ok, err) 100 | end 101 | 102 | sum, avg, max = stat(data) 103 | end 104 | 105 | local bytes = string.match(desc, "(%d+) bytes") 106 | if bytes then 107 | bytes = tonumber(bytes) 108 | bytes = bytes / 1000 * (1e9/avg) 109 | else 110 | bytes = 1/0 111 | end 112 | print(string.format("FINISHED in\t%s (%d op/s, %.2fk bytes/s)\nAVG\t%s\tMAX\t%s", hmt(sum), 1e9/avg, bytes, hmt(avg), hmt(max))) 113 | print(string.rep("-", 64)) 114 | 115 | if expected ~= nil then 116 | assert(expected == ok, "expected " .. expected .. "(" .. (#expected or 0) .. " bytes)" .. 117 | ", but got " .. ok .. "(" .. (#ok or 0) .. " bytes)") 118 | end 119 | end 120 | 121 | local function set_iteration(i) 122 | ITER = i 123 | end 124 | 125 | print("LOADING TEST FROM " .. arg[0]) 126 | 127 | write_seperator() 128 | 129 | return { 130 | test = test, 131 | set_iteration = set_iteration, 132 | write_seperator = write_seperator, 133 | set_no_count_iter = function(s) 134 | no_count_iter = s 135 | end, 136 | } 137 | -------------------------------------------------------------------------------- /examples/perf/test_cipher.lua: -------------------------------------------------------------------------------- 1 | local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") 2 | package.path = path .. "/?.lua;" .. package.path 3 | 4 | local test = require "framework".test 5 | local set_iteration = require "framework".set_iteration 6 | local write_seperator = require "framework".write_seperator 7 | local cipher = require "resty.openssl.cipher" 8 | local version = require("resty.openssl.version") 9 | 10 | local key = string.rep("0", 32) 11 | local iv = string.rep("0", 16) 12 | local data = string.rep("1", 4096) 13 | local aad = string.rep("2", 10) 14 | 15 | set_iteration(100000) 16 | 17 | for _, t in ipairs({"aes-256-cbc", "aes-256-gcm", "chacha20-poly1305"}) do 18 | for _, op in ipairs({"encrypt", "decrypt"}) do 19 | -- the fips version of boringssl we used seems don't have chacha20 20 | if t == "chacha20-poly1305" and (not version.OPENSSL_111_OR_LATER or version.BORINGSSL) then 21 | goto continue 22 | end 23 | 24 | local c = assert(cipher.new(t)) 25 | local _iv = iv 26 | local _aad 27 | if t == "aes-256-gcm" or t == "chacha20-poly1305" then 28 | _iv = string.rep("0", 12) 29 | _aad = aad 30 | end 31 | 32 | if op == "encrypt" then 33 | test("encrypt with " .. t .. " on " .. #data .. " bytes", function() 34 | return c:encrypt(key, _iv, data, false, _aad) 35 | end) 36 | 37 | else 38 | local ciphertext = assert(c:encrypt(key, _iv, data, false, _aad)) 39 | 40 | local tag 41 | if t == "aes-256-gcm" or t == "chacha20-poly1305" then 42 | tag = assert(c:get_aead_tag()) 43 | end 44 | test("decrypt with " .. t .. " on " .. #ciphertext .. " bytes", function() 45 | return c:decrypt(key, _iv, ciphertext, false, _aad, tag) 46 | end) 47 | end 48 | ::continue:: 49 | end 50 | 51 | write_seperator() 52 | end 53 | -------------------------------------------------------------------------------- /examples/perf/test_pkey_asymm.lua: -------------------------------------------------------------------------------- 1 | local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") 2 | package.path = path .. "/?.lua;" .. package.path 3 | 4 | local test = require "framework".test 5 | local set_iteration = require "framework".set_iteration 6 | local write_seperator = require "framework".write_seperator 7 | local pkey = require "resty.openssl.pkey" 8 | local version = require("resty.openssl.version") 9 | local data = string.rep("=", 200) 10 | 11 | set_iteration(1000) 12 | 13 | local rsa = pkey.new({ type = "RSA", bits = 4096 }) 14 | 15 | for _, op in ipairs({"encrypt", "decrypt"}) do 16 | if op == "encrypt" then 17 | test("encrypt with RSA on " .. #data .. " bytes", function() 18 | return rsa:encrypt(data) 19 | end) 20 | 21 | else 22 | 23 | local ciphertext = assert(rsa:encrypt(data)) 24 | test("decrypt with RSA on " .. #ciphertext .. " bytes", function() 25 | return rsa:decrypt(ciphertext) 26 | end) 27 | end 28 | end 29 | 30 | write_seperator() 31 | 32 | for _, t in ipairs({"RSA", "EC", "Ed25519", "Ed448"}) do 33 | for _, op in ipairs({"sign", "verify"}) do 34 | -- the fips version of boringssl we used seems don't have ed448 35 | if (t == "Ed25519" and not version.OPENSSL_111_OR_LATER) or (t == "Ed448" and version.BORINGSSL) then 36 | goto continue 37 | end 38 | 39 | local opts = { type = t } 40 | if t == "EC" then 41 | opts.curve = "prime256v1" 42 | elseif t == "RSA" then 43 | opts.bits = 4096 44 | end 45 | 46 | local c = assert(pkey.new(opts)) 47 | local md_alg 48 | if t == "RSA" or t == "EC" then 49 | md_alg = "SHA256" 50 | end 51 | 52 | if op == "sign" then 53 | test("sign with " .. t .. (md_alg and ("-" .. md_alg) or "") .. " on " .. #data .. " bytes", function() 54 | return c:sign(data, md_alg) 55 | end) 56 | 57 | else 58 | local sig = assert(c:sign(data, md_alg)) 59 | 60 | test("verify with " .. t .. (md_alg and ("-" .. md_alg) or "") .. " on " .. #data .. " bytes", function() 61 | return c:verify(sig, data, md_alg) 62 | end) 63 | end 64 | ::continue:: 65 | end 66 | 67 | write_seperator() 68 | end 69 | -------------------------------------------------------------------------------- /examples/perf/test_pkey_codec.lua: -------------------------------------------------------------------------------- 1 | local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") 2 | package.path = path .. "/?.lua;" .. package.path 3 | 4 | local test = require "framework".test 5 | local write_seperator = require "framework".write_seperator 6 | local pkey = require "resty.openssl.pkey" 7 | local example_pkey = assert(pkey.new()) 8 | 9 | for _, t in ipairs({"PEM", "DER", "JWK"}) do 10 | for _, op in ipairs({"load", "export"}) do 11 | for _, p in ipairs({"public", "private"}) do 12 | 13 | if op == "load" then 14 | local txt = assert(example_pkey:tostring(p, t)) 15 | local opts = { 16 | format = t, 17 | } 18 | if t ~= "JWK" then 19 | opts.type = p == "public" and "pu" or "pr" 20 | end 21 | 22 | test("load " .. t .. " " .. p .. " key", function() 23 | return pkey.new(txt, opts) 24 | end) 25 | 26 | else 27 | test("export " .. t .. " " .. p .. " key", function() 28 | return example_pkey:tostring(p, t) 29 | end) 30 | end 31 | 32 | end 33 | end 34 | 35 | write_seperator() 36 | end 37 | -------------------------------------------------------------------------------- /examples/perf/test_x509_codec.lua: -------------------------------------------------------------------------------- 1 | local path = debug.getinfo(1, "S").source:sub(2):match("(.*/)") 2 | package.path = path .. "/?.lua;" .. package.path 3 | 4 | local test = require "framework".test 5 | local write_seperator = require "framework".write_seperator 6 | local x509 = require "resty.openssl.x509" 7 | local cert = assert(io.open(path .. "../../t/fixtures/Github.pem")):read("*a") 8 | local example_x509 = assert(x509.new(cert)) 9 | 10 | for _, t in ipairs({"PEM", "DER"}) do 11 | for _, op in ipairs({"load", "export"}) do 12 | if op == "load" then 13 | local txt = assert(example_x509:tostring(t)) 14 | test("load " .. t .. " x509", function() 15 | return x509.new(txt, t) 16 | end) 17 | 18 | else 19 | test("export " .. t .. " x509", function() 20 | return example_x509:tostring(t) 21 | end) 22 | end 23 | end 24 | 25 | write_seperator() 26 | end 27 | -------------------------------------------------------------------------------- /examples/raw-sign-and-recover.lua: -------------------------------------------------------------------------------- 1 | local pkey = require("resty.openssl.pkey") 2 | 3 | -- sign_raw and verify_recover for RSA keys 4 | 5 | local priv = assert(pkey.new()) 6 | local pub = assert(pkey.new(priv:to_PEM("public"))) 7 | 8 | local original = "original text" 9 | 10 | -- same as nodejs: crypto.privateEncrypt 11 | -- php: openssl_private_encrypt 12 | local signed = assert(priv:sign_raw(original)) 13 | 14 | print("Signed message: " .. ngx.encode_base64(signed)) 15 | 16 | -- same as nodejs: crypto.publicDecrypt 17 | -- php: openssl_public_decrypt 18 | local recovered = assert(pub:verify_recover(signed)) 19 | print("Recovered message: " .. recovered) 20 | 21 | 22 | -- sign_raw and verify_raw for non RSA keys 23 | 24 | local priv = assert(pkey.new({ 25 | type = "EC", 26 | })) 27 | local pub = assert(pkey.new(priv:to_PEM("public"))) 28 | local md_alg = "sha512" 29 | 30 | local hashed = require "resty.openssl.digest".new(md_alg):final(original) 31 | 32 | local signed = assert(priv:sign_raw(hashed)) 33 | 34 | print("Signed message: " .. ngx.encode_base64(signed)) 35 | 36 | local verified = assert(pub:verify_raw(signed, hashed, md_alg)) 37 | print("Verification result: ", verified) 38 | -------------------------------------------------------------------------------- /examples/self-signed.lua: -------------------------------------------------------------------------------- 1 | local openssl_bignum = require "resty.openssl.bn" 2 | local openssl_rand = require "resty.openssl.rand" 3 | local openssl_pkey = require "resty.openssl.pkey" 4 | local x509 = require "resty.openssl.x509" 5 | local x509_extension = require "resty.openssl.x509.extension" 6 | local x509_name = require "resty.openssl.x509.name" 7 | 8 | -- taken from https://github.com/Kong/kong/blob/master/kong/cmd/utils/prefix_handler.lua 9 | local function generate_self_signed() 10 | local key = openssl_pkey.new { bits = 2048 } 11 | 12 | local crt = x509.new() 13 | assert(crt:set_pubkey(key)) 14 | assert(crt:set_version(3)) 15 | assert(crt:set_serial_number(openssl_bignum.from_binary(openssl_rand.bytes(16)))) 16 | 17 | -- last for 20 years 18 | local now = os.time() 19 | assert(crt:set_not_before(now)) 20 | assert(crt:set_not_after(now + 86400 * 20 * 365)) 21 | 22 | local name = assert(x509_name.new() 23 | :add("C", "US") 24 | :add("ST", "California") 25 | :add("L", "San Francisco") 26 | :add("O", "Kong") 27 | :add("OU", "IT Department") 28 | :add("CN", "localhost")) 29 | 30 | assert(crt:set_subject_name(name)) 31 | assert(crt:set_issuer_name(name)) 32 | 33 | -- Not a CA 34 | assert(crt:set_basic_constraints { CA = false }) 35 | assert(crt:set_basic_constraints_critical(true)) 36 | 37 | -- Only allowed to be used for TLS connections (client or server) 38 | assert(crt:add_extension(x509_extension.new("extendedKeyUsage", 39 | "serverAuth,clientAuth"))) 40 | 41 | -- RFC-3280 4.2.1.2 42 | assert(crt:add_extension(x509_extension.new("subjectKeyIdentifier", "hash", { 43 | subject = crt 44 | }))) 45 | 46 | -- All done; sign 47 | assert(crt:sign(key)) 48 | 49 | return crt, key 50 | end 51 | 52 | 53 | local crt, key = generate_self_signed() 54 | 55 | do -- write key out 56 | local fd = assert(io.open("key.pem", "w+b")) 57 | local pem = assert(key:to_PEM("private")) 58 | assert(fd:write(pem)) 59 | fd:close() 60 | end 61 | 62 | print("================== private key =================") 63 | os.execute("openssl pkey -in key.pem -noout -text") 64 | os.remove("key.pem") 65 | 66 | do -- write cert out 67 | local fd = assert(io.open("cert.pem", "w+b")) 68 | local pem = assert(crt:to_PEM("private")) 69 | assert(fd:write(pem)) 70 | fd:close() 71 | end 72 | 73 | print("\n\n") 74 | print("================== certificate =================") 75 | os.execute("openssl x509 -in cert.pem -noout -text") 76 | os.remove("cert.pem") -------------------------------------------------------------------------------- /examples/tls-alpn-01.lua: -------------------------------------------------------------------------------- 1 | local pkey = require("resty.openssl.pkey") 2 | local digest = require("resty.openssl.digest") 3 | local x509 = require("resty.openssl.x509") 4 | local altname = require("resty.openssl.x509.altname") 5 | local extension = require("resty.openssl.x509.extension") 6 | local objects = require("resty.openssl.objects") 7 | 8 | -- creates the ACME Identifier NID into openssl's internal lookup table 9 | -- if it doesn't exist 10 | local id_pe_acmeIdentifier = "1.3.6.1.5.5.7.1.31" 11 | local nid = objects.txt2nid(id_pe_acmeIdentifier) 12 | if not nid or nid == 0 then 13 | nid = objects.create( 14 | id_pe_acmeIdentifier, -- nid 15 | "pe-acmeIdentifier", -- sn 16 | "ACME Identifier" -- ln 17 | ) 18 | end 19 | 20 | -- generate the tls-alpn-01 challenge certificate/key per 21 | -- https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-07 22 | -- with given domain name and challenge token 23 | local function serve_challenge_cert(domain, challenge) 24 | local dgst = assert(digest.new("sha256"):final(challenge)) 25 | 26 | -- There're two ways to set ASN.1 octect string to the extension 27 | -- The recommanded way is to pass the string directly to extension.from_der() 28 | local _, err = extension.from_der(dgst, nid, true) 29 | if err then 30 | return nil, nil, err 31 | end 32 | -- OR we put the ASN.1 signature for this string by ourselves 33 | -- 0x04: OCTET STRING 34 | -- 0x20: length 35 | local dgst_hex = "DER:0420" .. dgst:gsub("(.)", function(s) return string.format("%02x", string.byte(s)) end) 36 | local ext, err = extension.new(nid, dgst_hex) 37 | if err then 38 | return nil, nil, err 39 | end 40 | ext:set_critical(true) 41 | 42 | local key = pkey.new() 43 | local cert = x509.new() 44 | cert:set_pubkey(key) 45 | 46 | cert:add_extension(ext) 47 | 48 | local alt = assert(altname.new():add( 49 | "DNS", domain 50 | )) 51 | local _, err = cert:set_subject_alt_name(alt) 52 | if err then 53 | return nil, nil, err 54 | end 55 | cert:sign(key) 56 | 57 | return key, cert 58 | end 59 | -------------------------------------------------------------------------------- /examples/x25519-dh.lua: -------------------------------------------------------------------------------- 1 | local pkey = require("resty.openssl.pkey") 2 | 3 | -- alice's private key 4 | local alice_priv = assert(pkey.new({ 5 | type = "X25519" 6 | })) 7 | -- alice's public key, shared with bob 8 | local alice_pub = assert(pkey.new(alice_priv:to_PEM("public"))) 9 | 10 | -- bob's private key 11 | local bob_priv = assert(pkey.new({ 12 | type = "X25519" 13 | })) 14 | -- bobs' public key, shared with alice 15 | local bob_pub = assert(pkey.new(bob_priv:to_PEM("public"))) 16 | 17 | ngx.say("alice and bob hold ", 18 | alice_priv:to_PEM() == bob_priv:to_PEM() and "same keys" or "different keys") 19 | 20 | ngx.say("") 21 | 22 | local k1 = assert(alice_priv:derive(bob_pub)) 23 | ngx.say("alice use this key to talk with bob: ", ngx.encode_base64(k1)) 24 | 25 | local k2 = assert(bob_priv:derive(alice_pub)) 26 | ngx.say("bob use this key to talk with alice: ", ngx.encode_base64(k2)) 27 | 28 | ngx.say("") 29 | 30 | ngx.say(k1 == k2 and "key exchange is correct" or "key exchange is not correct") 31 | 32 | -------------------------------------------------------------------------------- /lib/resty/openssl/asn1.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_str = ffi.string 4 | local floor = math.floor 5 | 6 | local asn1_macro = require("resty.openssl.include.asn1") 7 | 8 | -- https://github.com/wahern/luaossl/blob/master/src/openssl.c 9 | local function isleap(year) 10 | return (year % 4) == 0 and ((year % 100) > 0 or (year % 400) == 0) 11 | end 12 | 13 | local past = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 } 14 | local function yday(year, mon, mday) 15 | local d = past[mon] + mday - 1 16 | if mon > 2 and isleap(year) then 17 | d = d + 1 18 | end 19 | return d 20 | end 21 | 22 | local function leaps(year) 23 | return floor(year / 400) + floor(year / 4) - floor(year / 100) 24 | end 25 | 26 | local function asn1_to_unix(asn1) 27 | if asn1 == nil then 28 | return nil, "except an ASN1 instance at #1, got nil" 29 | end 30 | 31 | local s = asn1_macro.ASN1_STRING_get0_data(asn1) 32 | s = ffi_str(s) 33 | -- V_ASN1_UTCTIME 190303223958Z 34 | -- V_ASN1_GENERALIZEDTIME 21190822162753Z 35 | local yyoffset = 2 36 | local year 37 | -- # define V_ASN1_GENERALIZEDTIME 24 38 | if C.ASN1_STRING_type(asn1) == 24 then 39 | yyoffset = 4 40 | year = tonumber(s:sub(1, yyoffset)) 41 | else 42 | year = tonumber(s:sub(1, yyoffset)) 43 | year = year + (year < 50 and 2000 or 1900) 44 | end 45 | local month = tonumber(s:sub(yyoffset+1, yyoffset+2)) 46 | if month > 12 or month < 1 then 47 | return nil, "asn1.asn1_to_unix: bad format " .. s 48 | end 49 | local day = tonumber(s:sub(yyoffset+3, yyoffset+4)) 50 | if day > 31 or day < 1 then 51 | return nil, "asn1.asn1_to_unix: bad format " .. s 52 | end 53 | local hour = tonumber(s:sub(yyoffset+5, yyoffset+6)) 54 | if hour > 23 or hour < 0 then 55 | return nil, "asn1.asn1_to_unix: bad format " .. s 56 | end 57 | local minute = tonumber(s:sub(yyoffset+7, yyoffset+8)) 58 | if minute > 59 or hour < 0 then 59 | return nil, "asn1.asn1_to_unix: bad format " .. s 60 | end 61 | local second = tonumber(s:sub(yyoffset+9, yyoffset+10)) 62 | if second > 59 or second < 0 then 63 | return nil, "asn1.asn1_to_unix: bad format " .. s 64 | end 65 | 66 | local tm 67 | tm = (year - 1970) * 365 68 | tm = tm + leaps(year - 1) - leaps(1969) 69 | tm = (tm + yday(year, month, day)) * 24 70 | tm = (tm + hour) * 60 71 | tm = (tm + minute) * 60 72 | tm = tm + second 73 | 74 | -- offset? 75 | local sign = s:sub(yyoffset+11, yyoffset+11) 76 | if sign == "+" or sign == "-" then 77 | local sgn = sign == "+" and 1 or -1 78 | local hh = tonumber(s:sub(yyoffset+12, yyoffset+13) or 'no') 79 | local mm = tonumber(s:sub(yyoffset+14, yyoffset+15) or 'no') 80 | if not hh or not mm then 81 | return nil, "asn1.asn1_to_unix: bad format " .. s 82 | end 83 | tm = tm + sgn * (hh * 3600 + mm * 60) 84 | end 85 | 86 | return tm 87 | end 88 | 89 | return { 90 | asn1_to_unix = asn1_to_unix, 91 | } 92 | -------------------------------------------------------------------------------- /lib/resty/openssl/auxiliary/bio.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_new = ffi.new 5 | local ffi_str = ffi.string 6 | 7 | require "resty.openssl.include.bio" 8 | local format_error = require("resty.openssl.err").format_error 9 | 10 | local function read_wrap(f, ...) 11 | if type(f) ~= "cdata" then -- should be explictly a function 12 | return nil, "bio_util.read_wrap: expect a function at #1" 13 | end 14 | 15 | local bio_method = C.BIO_s_mem() 16 | if bio_method == nil then 17 | return nil, "bio_util.read_wrap: BIO_s_mem() failed" 18 | end 19 | local bio = C.BIO_new(bio_method) 20 | ffi_gc(bio, C.BIO_free) 21 | 22 | -- BIO_reset; #define BIO_CTRL_RESET 1 23 | local code = C.BIO_ctrl(bio, 1, 0, nil) 24 | if code ~= 1 then 25 | return nil, "bio_util.read_wrap: BIO_ctrl() failed: " .. code 26 | end 27 | 28 | local code = f(bio, ...) 29 | if code ~= 1 then 30 | return nil, format_error(f, code) 31 | end 32 | 33 | local buf = ffi_new("char *[1]") 34 | 35 | -- BIO_get_mem_data; #define BIO_CTRL_INFO 3 36 | local length = C.BIO_ctrl(bio, 3, 0, buf) 37 | 38 | return ffi_str(buf[0], length) 39 | end 40 | 41 | return { 42 | read_wrap = read_wrap, 43 | } -------------------------------------------------------------------------------- /lib/resty/openssl/auxiliary/compat.lua: -------------------------------------------------------------------------------- 1 | local nkeys 2 | 3 | do 4 | local pok, perr = pcall(require, "table.nkeys") 5 | if pok then 6 | nkeys = perr 7 | else 8 | nkeys = function(tbl) 9 | local cnt = 0 10 | for _ in pairs(tbl) do 11 | cnt = cnt + 1 12 | end 13 | return cnt 14 | end 15 | end 16 | end 17 | 18 | local noop = function() end 19 | 20 | local log_warn, log_debug 21 | local encode_base64url, decode_base64url 22 | 23 | if ngx then 24 | log_warn = function(...) 25 | ngx.log(ngx.WARN, ...) 26 | end 27 | 28 | log_debug = function(...) 29 | ngx.log(ngx.DEBUG, ...) 30 | end 31 | 32 | local b64 = require("ngx.base64") 33 | encode_base64url = b64.encode_base64url 34 | decode_base64url = b64.decode_base64url 35 | 36 | else 37 | log_warn = noop 38 | log_debug = noop 39 | 40 | local pok, basexx = pcall(require, "basexx") 41 | if pok then 42 | encode_base64url = basexx.to_url64 43 | decode_base64url = basexx.from_url64 44 | else 45 | encode_base64url = function() 46 | error("no base64 library is found, needs either ngx.base64 or basexx") 47 | end 48 | decode_base64url = encode_base64url 49 | end 50 | 51 | end 52 | 53 | local json 54 | do 55 | local pok, perr = pcall(require, "cjson.safe") 56 | if pok then 57 | json = perr 58 | else 59 | local pok, perr = pcall(require, "dkjson") 60 | if pok then 61 | json = perr 62 | end 63 | end 64 | 65 | if not json then 66 | json = setmetatable({}, { 67 | __index = function() 68 | return function() 69 | error("no JSON library is found, needs either cjson or dkjson") 70 | end 71 | end, 72 | }) 73 | end 74 | end 75 | 76 | 77 | return { 78 | nkeys = nkeys, 79 | log_warn = log_warn, 80 | log_debug = log_debug, 81 | encode_base64url = encode_base64url, 82 | decode_base64url = decode_base64url, 83 | json = json, 84 | } -------------------------------------------------------------------------------- /lib/resty/openssl/auxiliary/ctypes.lua: -------------------------------------------------------------------------------- 1 | -- Put common type definition at the same place for convenience 2 | -- and standarlization 3 | local ffi = require "ffi" 4 | 5 | --[[ 6 | TYPE_ptr: usually used to define a pointer (to cast or something) 7 | char* var_name; // <- we use char_ptr 8 | 9 | ptr_of_TYPE: usually used to pass the pointer of an object that 10 | is already allocated. so that we can also set value of it as well 11 | 12 | int p = 2; // ptr_of_int(); ptr_of_int[0] = 2; 13 | plus_one(&p); // <- we use ptr_of_int 14 | ]] 15 | 16 | return { 17 | void_ptr = ffi.typeof("void *"), 18 | ptr_of_uint64 = ffi.typeof("uint64_t[1]"), 19 | ptr_of_uint = ffi.typeof("unsigned int[1]"), 20 | ptr_of_size_t = ffi.typeof("size_t[1]"), 21 | ptr_of_int = ffi.typeof("int[1]"), 22 | null = ffi.new("void *"), -- hack wher ngx.null is not available 23 | 24 | uchar_array = ffi.typeof("unsigned char[?]"), 25 | uchar_ptr = ffi.typeof("unsigned char*"), 26 | 27 | SIZE_MAX = math.pow(2, 64), -- nginx set _FILE_OFFSET_BITS to 64 28 | } -------------------------------------------------------------------------------- /lib/resty/openssl/ctx.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | 5 | require "resty.openssl.include.ossl_typ" 6 | local format_error = require("resty.openssl.err").format_error 7 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 8 | 9 | ffi.cdef [[ 10 | OSSL_LIB_CTX *OSSL_LIB_CTX_new(void); 11 | int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file); 12 | void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx); 13 | ]] 14 | 15 | local ossl_lib_ctx 16 | 17 | local function new(request_context_only, conf_file) 18 | if not OPENSSL_3X then 19 | return false, "ctx is only supported from OpenSSL 3.0" 20 | end 21 | 22 | local ctx = C.OSSL_LIB_CTX_new() 23 | ffi_gc(ctx, C.OSSL_LIB_CTX_free) 24 | 25 | if conf_file and C.OSSL_LIB_CTX_load_config(ctx, conf_file) ~= 1 then 26 | return false, format_error("ctx.new") 27 | end 28 | 29 | if request_context_only and ngx then 30 | ngx.ctx.ossl_lib_ctx = ctx 31 | else 32 | ossl_lib_ctx = ctx 33 | end 34 | 35 | return true 36 | end 37 | 38 | local function free(request_context_only) 39 | if not OPENSSL_3X then 40 | return false, "ctx is only supported from OpenSSL 3.0" 41 | end 42 | 43 | if request_context_only and ngx then 44 | ngx.ctx.ossl_lib_ctx = nil 45 | else 46 | ossl_lib_ctx = nil 47 | end 48 | 49 | return true 50 | end 51 | 52 | local test_request 53 | 54 | do 55 | 56 | local ok, exdata = pcall(require, "thread.exdata") 57 | if ok and exdata then 58 | test_request = function() 59 | local r = exdata() 60 | if r ~= nil then 61 | return not not r 62 | end 63 | end 64 | 65 | else 66 | local getfenv = getfenv 67 | 68 | function test_request() 69 | return not not getfenv(0).__ngx_req 70 | end 71 | end 72 | end 73 | 74 | return { 75 | new = new, 76 | free = free, 77 | get_libctx = function() return test_request() and ngx.ctx.ossl_lib_ctx or ossl_lib_ctx end, 78 | } -------------------------------------------------------------------------------- /lib/resty/openssl/dh.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "resty.openssl.include.dh" 5 | local bn_lib = require "resty.openssl.bn" 6 | 7 | local format_error = require("resty.openssl.err").format_error 8 | 9 | local _M = {} 10 | 11 | _M.params = {"public", "private", "p", "q", "g"} 12 | 13 | local empty_table = {} 14 | local bn_ptrptr_ct = ffi.typeof("const BIGNUM *[1]") 15 | function _M.get_parameters(dh_st) 16 | return setmetatable(empty_table, { 17 | __index = function(_, k) 18 | local ptr, ret 19 | ptr = bn_ptrptr_ct() 20 | 21 | if k == 'p' then 22 | C.DH_get0_pqg(dh_st, ptr, nil, nil) 23 | elseif k == 'q' then 24 | C.DH_get0_pqg(dh_st, nil, ptr, nil) 25 | elseif k == 'g' then 26 | C.DH_get0_pqg(dh_st, nil, nil, ptr) 27 | elseif k == 'public' then 28 | C.DH_get0_key(dh_st, ptr, nil) 29 | elseif k == 'private' then 30 | C.DH_get0_key(dh_st, nil, ptr) 31 | else 32 | return nil, "rsa.get_parameters: unknown parameter \"" .. k .. "\" for RSA key" 33 | end 34 | 35 | ret = ptr[0] 36 | 37 | if ret == nil then 38 | return nil 39 | end 40 | return bn_lib.dup(ret) 41 | end 42 | }), nil 43 | end 44 | 45 | local function dup_bn_value(v) 46 | if not bn_lib.istype(v) then 47 | return nil, "expect value to be a bn instance" 48 | end 49 | local bn = C.BN_dup(v.ctx) 50 | if bn == nil then 51 | return nil, "BN_dup() failed" 52 | end 53 | return bn 54 | end 55 | 56 | function _M.set_parameters(dh_st, opts) 57 | local err 58 | local opts_bn = {} 59 | -- remember which parts of BNs has been added to dh_st, they should be freed 60 | -- by DH_free and we don't cleanup them on failure 61 | local cleanup_from_idx = 1 62 | -- dup input 63 | local do_set_key, do_set_pqg 64 | 65 | while true do -- luacheck: ignore 66 | for k, v in pairs(opts) do 67 | opts_bn[k], err = dup_bn_value(v) 68 | if err then 69 | -- luacheck: ignore 70 | err = "dh.set_parameters: cannot process parameter \"" .. k .. "\":" .. err 71 | break 72 | end 73 | 74 | if k == "private" or k == "public" then 75 | do_set_key = true 76 | elseif k == "p" or k == "q" or k == "g" then 77 | do_set_pqg = true 78 | end 79 | end 80 | 81 | local code 82 | if do_set_key then 83 | code = C.DH_set0_key(dh_st, opts_bn["public"], opts_bn["private"]) 84 | if code == 0 then 85 | err = format_error("dh.set_parameters: DH_set0_key") 86 | break 87 | end 88 | end 89 | 90 | cleanup_from_idx = cleanup_from_idx + 2 91 | if do_set_pqg then 92 | code = C.DH_set0_pqg(dh_st, opts_bn["p"], opts_bn["q"], opts_bn["g"]) 93 | if code == 0 then 94 | err = format_error("dh.set_parameters: DH_set0_pqg") 95 | break 96 | end 97 | end 98 | 99 | return true 100 | end 101 | 102 | for i, k in pairs(_M.params) do 103 | if i >= cleanup_from_idx then 104 | C.BN_free(opts_bn[k]) 105 | end 106 | end 107 | return false, err 108 | end 109 | 110 | return _M 111 | -------------------------------------------------------------------------------- /lib/resty/openssl/digest.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_str = ffi.string 5 | 6 | require "resty.openssl.include.evp.md" 7 | local ctypes = require "resty.openssl.auxiliary.ctypes" 8 | local ctx_lib = require "resty.openssl.ctx" 9 | local format_error = require("resty.openssl.err").format_error 10 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 11 | 12 | local _M = {} 13 | local mt = {__index = _M} 14 | 15 | local md_ctx_ptr_ct = ffi.typeof('EVP_MD_CTX*') 16 | 17 | function _M.new(typ, properties) 18 | local ctx = C.EVP_MD_CTX_new() 19 | if ctx == nil then 20 | return nil, "digest.new: failed to create EVP_MD_CTX" 21 | end 22 | ffi_gc(ctx, C.EVP_MD_CTX_free) 23 | 24 | local err_new = string.format("digest.new: invalid digest type \"%s\"", typ) 25 | 26 | local algo 27 | if typ == "null" then 28 | algo = C.EVP_md_null() 29 | else 30 | if OPENSSL_3X then 31 | algo = C.EVP_MD_fetch(ctx_lib.get_libctx(), typ or 'sha1', properties) 32 | ffi_gc(algo, C.EVP_MD_free) 33 | else 34 | algo = C.EVP_get_digestbyname(typ or 'sha1') 35 | end 36 | if algo == nil then 37 | return nil, format_error(err_new) 38 | end 39 | end 40 | 41 | local code = C.EVP_DigestInit_ex(ctx, algo, nil) 42 | if code ~= 1 then 43 | return nil, format_error(err_new) 44 | end 45 | 46 | return setmetatable({ 47 | ctx = ctx, 48 | algo = algo, 49 | buf = ctypes.uchar_array(OPENSSL_3X and C.EVP_MD_get_size(algo) or C.EVP_MD_size(algo)), 50 | }, mt), nil 51 | end 52 | 53 | function _M.istype(l) 54 | return l and l.ctx and ffi.istype(md_ctx_ptr_ct, l.ctx) 55 | end 56 | 57 | function _M:get_provider_name() 58 | if not OPENSSL_3X then 59 | return false, "digest:get_provider_name is not supported" 60 | end 61 | local p = C.EVP_MD_get0_provider(self.algo) 62 | if p == nil then 63 | return nil 64 | end 65 | return ffi_str(C.OSSL_PROVIDER_get0_name(p)) 66 | end 67 | 68 | if OPENSSL_3X then 69 | local param_lib = require "resty.openssl.param" 70 | _M.settable_params, _M.set_params, _M.gettable_params, _M.get_param = param_lib.get_params_func("EVP_MD_CTX") 71 | end 72 | 73 | function _M:update(...) 74 | for _, s in ipairs({...}) do 75 | if C.EVP_DigestUpdate(self.ctx, s, #s) ~= 1 then 76 | return false, format_error("digest:update") 77 | end 78 | end 79 | return true, nil 80 | end 81 | 82 | local result_length = ctypes.ptr_of_uint() 83 | 84 | function _M:final(s) 85 | if s then 86 | if C.EVP_DigestUpdate(self.ctx, s, #s) ~= 1 then 87 | return false, format_error("digest:final") 88 | end 89 | end 90 | 91 | -- no return value of EVP_DigestFinal_ex 92 | C.EVP_DigestFinal_ex(self.ctx, self.buf, result_length) 93 | if result_length[0] == nil or result_length[0] <= 0 then 94 | return nil, format_error("digest:final: EVP_DigestFinal_ex") 95 | end 96 | return ffi_str(self.buf, result_length[0]) 97 | end 98 | 99 | 100 | function _M:reset() 101 | local code = C.EVP_DigestInit_ex(self.ctx, self.algo, nil) 102 | if code ~= 1 then 103 | return false, format_error("digest:reset") 104 | end 105 | 106 | return true 107 | end 108 | 109 | return _M 110 | -------------------------------------------------------------------------------- /lib/resty/openssl/ecx.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_str = ffi.string 4 | 5 | require "resty.openssl.include.ec" 6 | require "resty.openssl.include.evp" 7 | local ctypes = require "resty.openssl.auxiliary.ctypes" 8 | local format_error = require("resty.openssl.err").format_error 9 | 10 | local _M = {} 11 | 12 | _M.params = {"public", "private"} 13 | 14 | local empty_table = {} 15 | 16 | local MAX_ECX_KEY_SIZE = 114 -- ed448 uses 114 bytes 17 | 18 | function _M.get_parameters(evp_pkey_st) 19 | return setmetatable(empty_table, { 20 | __index = function(_, k) 21 | local buf = ctypes.uchar_array(MAX_ECX_KEY_SIZE) 22 | local length = ctypes.ptr_of_size_t(MAX_ECX_KEY_SIZE) 23 | 24 | if k == 'public' or k == "pub_key" then 25 | if C.EVP_PKEY_get_raw_public_key(evp_pkey_st, buf, length) ~= 1 then 26 | error(format_error("ecx.get_parameters: EVP_PKEY_get_raw_private_key")) 27 | end 28 | elseif k == 'private' or k == "priv ~=_key" then 29 | if C.EVP_PKEY_get_raw_private_key(evp_pkey_st, buf, length) ~= 1 then 30 | return nil, format_error("ecx.get_parameters: EVP_PKEY_get_raw_private_key") 31 | end 32 | else 33 | return nil, "ecx.get_parameters: unknown parameter \"" .. k .. "\" for EC key" 34 | end 35 | return ffi_str(buf, length[0]) 36 | end 37 | }), nil 38 | end 39 | 40 | function _M.set_parameters(key_type, evp_pkey_st, opts) 41 | -- for ecx keys we always create a new EVP_PKEY and release the old one 42 | -- Note: we allow to pass a nil as evp_pkey_st to create a new EVP_PKEY 43 | local key 44 | if opts.private then 45 | local priv = opts.private 46 | key = C.EVP_PKEY_new_raw_private_key(key_type, nil, priv, #priv) 47 | if key == nil then 48 | return nil, format_error("ecx.set_parameters: EVP_PKEY_new_raw_private_key") 49 | end 50 | elseif opts.public then 51 | local pub = opts.public 52 | key = C.EVP_PKEY_new_raw_public_key(key_type, nil, pub, #pub) 53 | if key == nil then 54 | return nil, format_error("ecx.set_parameters: EVP_PKEY_new_raw_public_key") 55 | end 56 | else 57 | return nil, "no parameter is specified" 58 | end 59 | 60 | if evp_pkey_st ~= nil then 61 | C.EVP_PKEY_free(evp_pkey_st) 62 | end 63 | return key 64 | 65 | end 66 | 67 | return _M 68 | -------------------------------------------------------------------------------- /lib/resty/openssl/err.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_str = ffi.string 4 | local ffi_sizeof = ffi.sizeof 5 | 6 | local ctypes = require "resty.openssl.auxiliary.ctypes" 7 | require "resty.openssl.include.err" 8 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 9 | 10 | local constchar_ptrptr = ffi.typeof("const char*[1]") 11 | 12 | local last_err_code = 0 13 | 14 | local function get_last_error_code() 15 | local code = C.ERR_peek_last_error() 16 | last_err_code = code == 0 and last_err_code or code 17 | 18 | return last_err_code 19 | end 20 | 21 | local function get_lib_error_string(code) 22 | code = code or get_last_error_code() 23 | 24 | local msg = C.ERR_lib_error_string(code) 25 | if msg == nil then 26 | return "unknown library" 27 | end 28 | 29 | return ffi_str(msg) 30 | end 31 | 32 | local function get_reason_error_string(code) 33 | code = code or get_last_error_code() 34 | 35 | local msg = C.ERR_reason_error_string(code) 36 | if msg == nil then 37 | return "" 38 | end 39 | 40 | return ffi_str(msg) 41 | end 42 | 43 | local function format_error(ctx, code, all_errors) 44 | local errors = {} 45 | if code then 46 | table.insert(errors, string.format("code: %d", code or 0)) 47 | end 48 | 49 | local line = ctypes.ptr_of_int() 50 | local path = constchar_ptrptr() 51 | local func = constchar_ptrptr() 52 | 53 | -- get the OpenSSL errors 54 | while C.ERR_peek_error() ~= 0 do 55 | local code 56 | if all_errors then 57 | if OPENSSL_3X then 58 | code = C.ERR_get_error_all(path, line, func, nil, nil) 59 | else 60 | code = C.ERR_get_error_line(path, line) 61 | end 62 | else 63 | if OPENSSL_3X then 64 | code = C.ERR_peek_last_error_all(path, line, func, nil, nil) 65 | else 66 | code = C.ERR_peek_last_error_line(path, line) 67 | end 68 | end 69 | 70 | last_err_code = code 71 | 72 | local abs_path = ffi_str(path[0]) 73 | -- ../crypto/asn1/a_d2i_fp.c => crypto/asn1/a_d2i_fp.c 74 | local start = abs_path:find("/") 75 | if start then 76 | abs_path = abs_path:sub(start+1) 77 | end 78 | 79 | local err_line 80 | 81 | if OPENSSL_3X then 82 | local reason_msg = get_reason_error_string(code) 83 | local lib_msg = get_lib_error_string(code) 84 | -- error:04800065:PEM routines:PEM_do_header:bad decrypt:crypto/pem/pem_lib.c:467: 85 | err_line = string.format("error:%X:%s:%s:%s:%s:%d:", 86 | code, lib_msg, ffi_str(func[0]), reason_msg, abs_path, line[0]) 87 | else 88 | local buf = ffi.new('char[256]') 89 | 90 | C.ERR_error_string_n(code, buf, ffi_sizeof(buf)) 91 | err_line = string.format("%s:%d:%s", 92 | abs_path, line[0], ffi_str(buf)) 93 | end 94 | 95 | table.insert(errors, err_line) 96 | 97 | if not all_errors then 98 | break 99 | end 100 | end 101 | 102 | C.ERR_clear_error() 103 | 104 | if #errors > 0 then 105 | return string.format("%s%s%s", (ctx or ""), (ctx and ": " or ""), table.concat(errors, " ")) 106 | else 107 | return string.format("%s failed", ctx) 108 | end 109 | end 110 | 111 | local function format_all_error(ctx, code) 112 | return format_error(ctx, code, true) 113 | end 114 | 115 | return { 116 | format_error = format_error, 117 | format_all_error = format_all_error, 118 | get_last_error_code = get_last_error_code, 119 | get_lib_error_string = get_lib_error_string, 120 | get_reason_error_string = get_reason_error_string, 121 | } 122 | -------------------------------------------------------------------------------- /lib/resty/openssl/hmac.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_str = ffi.string 5 | 6 | require "resty.openssl.include.hmac" 7 | require "resty.openssl.include.evp.md" 8 | local ctypes = require "resty.openssl.auxiliary.ctypes" 9 | local format_error = require("resty.openssl.err").format_error 10 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 11 | 12 | local _M = {} 13 | local mt = {__index = _M} 14 | 15 | local hmac_ctx_ptr_ct = ffi.typeof('HMAC_CTX*') 16 | 17 | -- Note: https://www.openssl.org/docs/manmaster/man3/HMAC_Init.html 18 | -- Replace with EVP_MAC_* functions for OpenSSL 3.0 19 | 20 | function _M.new(key, typ) 21 | local ctx = C.HMAC_CTX_new() 22 | if ctx == nil then 23 | return nil, "hmac.new: failed to create HMAC_CTX" 24 | end 25 | ffi_gc(ctx, C.HMAC_CTX_free) 26 | 27 | local algo = C.EVP_get_digestbyname(typ or 'sha1') 28 | if algo == nil then 29 | return nil, string.format("hmac.new: invalid digest type \"%s\"", typ) 30 | end 31 | 32 | local code = C.HMAC_Init_ex(ctx, key, #key, algo, nil) 33 | if code ~= 1 then 34 | return nil, format_error("hmac.new") 35 | end 36 | 37 | return setmetatable({ 38 | ctx = ctx, 39 | algo = algo, 40 | buf = ctypes.uchar_array(OPENSSL_3X and C.EVP_MD_get_size(algo) or C.EVP_MD_size(algo)), 41 | }, mt), nil 42 | end 43 | 44 | function _M.istype(l) 45 | return l and l.ctx and ffi.istype(hmac_ctx_ptr_ct, l.ctx) 46 | end 47 | 48 | function _M:update(...) 49 | for _, s in ipairs({...}) do 50 | if C.HMAC_Update(self.ctx, s, #s) ~= 1 then 51 | return false, format_error("hmac:update") 52 | end 53 | end 54 | return true, nil 55 | end 56 | 57 | local result_length = ctypes.ptr_of_uint() 58 | 59 | function _M:final(s) 60 | if s then 61 | if C.HMAC_Update(self.ctx, s, #s) ~= 1 then 62 | return false, format_error("hmac:final") 63 | end 64 | end 65 | 66 | if C.HMAC_Final(self.ctx, self.buf, result_length) ~= 1 then 67 | return nil, format_error("hmac:final: HMAC_Final") 68 | end 69 | return ffi_str(self.buf, result_length[0]) 70 | end 71 | 72 | function _M:reset() 73 | local code = C.HMAC_Init_ex(self.ctx, nil, 0, nil, nil) 74 | if code ~= 1 then 75 | return false, format_error("hmac:reset") 76 | end 77 | 78 | return true 79 | end 80 | 81 | return _M 82 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/asn1.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "resty.openssl.include.ossl_typ" 5 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 6 | 7 | ffi.cdef [[ 8 | typedef struct ASN1_VALUE_st ASN1_VALUE; 9 | 10 | typedef struct asn1_type_st ASN1_TYPE; 11 | 12 | ASN1_IA5STRING *ASN1_IA5STRING_new(); 13 | 14 | int ASN1_STRING_type(const ASN1_STRING *x); 15 | ASN1_STRING *ASN1_STRING_type_new(int type); 16 | int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); 17 | 18 | ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); 19 | BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); 20 | 21 | typedef long time_t; 22 | ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); 23 | 24 | int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); 25 | long ASN1_INTEGER_get(const ASN1_INTEGER *a); 26 | int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); 27 | 28 | int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); 29 | 30 | int ASN1_STRING_length(const ASN1_STRING *x); 31 | ]] 32 | 33 | local function declare_asn1_functions(typ, has_ex) 34 | local t = {} 35 | for i=1, 7 do 36 | t[i] = typ 37 | end 38 | 39 | ffi.cdef(string.format([[ 40 | %s *%s_new(void); 41 | void %s_free(%s *a); 42 | %s *%s_dup(%s *a); 43 | ]], unpack(t))) 44 | 45 | if OPENSSL_3X and has_ex then 46 | ffi.cdef(string.format([[ 47 | %s *%s_new_ex(OSSL_LIB_CTX *libctx, const char *propq); 48 | ]], typ, typ)) 49 | end 50 | end 51 | 52 | declare_asn1_functions("ASN1_INTEGER") 53 | declare_asn1_functions("ASN1_OBJECT") 54 | declare_asn1_functions("ASN1_STRING") 55 | declare_asn1_functions("ASN1_ENUMERATED") 56 | 57 | ffi.cdef[[ 58 | const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x); 59 | ]] 60 | local ASN1_STRING_get0_data = C.ASN1_STRING_get0_data 61 | 62 | return { 63 | ASN1_STRING_get0_data = ASN1_STRING_get0_data, 64 | declare_asn1_functions = declare_asn1_functions, 65 | has_new_ex = true, 66 | } 67 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/bio.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | typedef struct bio_method_st BIO_METHOD; 7 | long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); 8 | BIO *BIO_new_mem_buf(const void *buf, int len); 9 | BIO *BIO_new(const BIO_METHOD *type); 10 | int BIO_free(BIO *a); 11 | const BIO_METHOD *BIO_s_mem(void); 12 | // int BIO_read(BIO *b, void *data, int dlen); 13 | ]] 14 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/bn.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | local BN_ULONG 6 | if ffi.abi('64bit') then 7 | BN_ULONG = 'unsigned long long' 8 | else -- 32bit 9 | BN_ULONG = 'unsigned int' 10 | end 11 | 12 | ffi.cdef( 13 | [[ 14 | BIGNUM *BN_new(void); 15 | void BN_free(BIGNUM *a); 16 | 17 | BN_CTX *BN_CTX_new(void); 18 | // void BN_CTX_init(BN_CTX *c); 19 | void BN_CTX_free(BN_CTX *c); 20 | 21 | BIGNUM *BN_dup(const BIGNUM *a); 22 | int BN_add_word(BIGNUM *a, ]] .. BN_ULONG ..[[ w); 23 | int BN_set_word(BIGNUM *a, ]] .. BN_ULONG ..[[ w); 24 | ]] .. BN_ULONG ..[[ BN_get_word(BIGNUM *a); 25 | int BN_num_bits(const BIGNUM *a); 26 | BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); 27 | int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); 28 | 29 | int BN_hex2bn(BIGNUM **a, const char *str); 30 | int BN_dec2bn(BIGNUM **a, const char *str); 31 | int BN_bn2bin(const BIGNUM *a, unsigned char *to); 32 | char *BN_bn2hex(const BIGNUM *a); 33 | char *BN_bn2dec(const BIGNUM *a); 34 | 35 | int BN_bn2mpi(const BIGNUM *a, unsigned char *to); 36 | BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); 37 | 38 | void BN_set_negative(BIGNUM *a, int n); 39 | int BN_is_negative(const BIGNUM *a); 40 | 41 | int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 42 | int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); 43 | int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 44 | int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); 45 | int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, 46 | BN_CTX *ctx); 47 | int BN_mod_add(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, 48 | BN_CTX *ctx); 49 | int BN_mod_sub(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, 50 | BN_CTX *ctx); 51 | int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, 52 | BN_CTX *ctx); 53 | int BN_mod_sqr(BIGNUM *ret, BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); 54 | int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx); 55 | int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, 56 | const BIGNUM *m, BN_CTX *ctx); 57 | int BN_gcd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 58 | 59 | int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); 60 | int BN_rshift(BIGNUM *r, BIGNUM *a, int n); 61 | 62 | int BN_cmp(BIGNUM *a, BIGNUM *b); 63 | int BN_ucmp(BIGNUM *a, BIGNUM *b); 64 | 65 | int BN_is_zero(BIGNUM *a); 66 | int BN_is_one(BIGNUM *a); 67 | int BN_is_word(BIGNUM *a, ]] .. BN_ULONG ..[[ w); 68 | int BN_is_odd(BIGNUM *a); 69 | 70 | int BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb); 71 | int BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add, 72 | const BIGNUM *rem, BN_GENCB *cb); 73 | ]] 74 | ) -------------------------------------------------------------------------------- /lib/resty/openssl/include/conf.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | CONF *NCONF_new(CONF_METHOD *meth); 7 | void NCONF_free(CONF *conf); 8 | int NCONF_load_bio(CONF *conf, BIO *bp, long *eline); 9 | ]] -------------------------------------------------------------------------------- /lib/resty/openssl/include/crypto.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | ffi.cdef [[ 5 | int FIPS_mode(void); 6 | int FIPS_mode_set(int ONOFF); 7 | void CRYPTO_free(void *ptr, const char *file, int line); 8 | ]] 9 | 10 | local OPENSSL_free = function(ptr) 11 | -- file and line is for debuggin only, since we can't know the c file info 12 | -- the macro is expanded, just ignore this 13 | C.CRYPTO_free(ptr, "", 0) 14 | end 15 | 16 | 17 | return { 18 | OPENSSL_free = OPENSSL_free, 19 | } 20 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/dh.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "resty.openssl.include.ossl_typ" 5 | require "resty.openssl.include.objects" 6 | 7 | ffi.cdef [[ 8 | void DH_get0_pqg(const DH *dh, 9 | const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); 10 | int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); 11 | void DH_get0_key(const DH *dh, 12 | const BIGNUM **pub_key, const BIGNUM **priv_key); 13 | int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); 14 | 15 | DH *DH_get_1024_160(void); 16 | DH *DH_get_2048_224(void); 17 | DH *DH_get_2048_256(void); 18 | DH *DH_new_by_nid(int nid); 19 | ]]; 20 | 21 | 22 | local dh_groups = { 23 | -- per https://tools.ietf.org/html/rfc5114 24 | dh_1024_160 = function() return C.DH_get_1024_160() end, 25 | dh_2048_224 = function() return C.DH_get_2048_224() end, 26 | dh_2048_256 = function() return C.DH_get_2048_256() end, 27 | } 28 | 29 | local groups = { 30 | "ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192", 31 | "modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192", 32 | -- following cannot be used with FIPS provider 33 | "modp_1536", -- and the RFC5114 ones 34 | } 35 | 36 | for _, group in ipairs(groups) do 37 | local nid = C.OBJ_sn2nid(group) 38 | if nid ~= 0 then 39 | dh_groups[group] = function() return C.DH_new_by_nid(nid) end 40 | end 41 | end 42 | 43 | return { 44 | dh_groups = dh_groups, 45 | } 46 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/ec.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | /** Enum for the point conversion form as defined in X9.62 (ECDSA) 7 | * for the encoding of a elliptic curve point (x,y) */ 8 | typedef enum { 9 | /** the point is encoded as z||x, where the octet z specifies 10 | * which solution of the quadratic equation y is */ 11 | POINT_CONVERSION_COMPRESSED = 2, 12 | /** the point is encoded as z||x||y, where z is the octet 0x04 */ 13 | POINT_CONVERSION_UNCOMPRESSED = 4, 14 | /** the point is encoded as z||x||y, where the octet z specifies 15 | * which solution of the quadratic equation y is */ 16 | POINT_CONVERSION_HYBRID = 6 17 | } point_conversion_form_t; 18 | 19 | EC_KEY *EC_KEY_new(void); 20 | void EC_KEY_free(EC_KEY *key); 21 | 22 | EC_GROUP *EC_GROUP_new_by_curve_name(int nid); 23 | void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); 24 | void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 25 | point_conversion_form_t form); 26 | // void EC_GROUP_set_curve_name(EC_GROUP *group, int nid); 27 | int EC_GROUP_get_curve_name(const EC_GROUP *group); 28 | 29 | void EC_GROUP_free(EC_GROUP *group); 30 | 31 | BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, 32 | point_conversion_form_t form, BIGNUM *, BN_CTX *); 33 | int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, 34 | BIGNUM *x, BIGNUM *y, BN_CTX *ctx); 35 | EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, const BIGNUM *bn, 36 | EC_POINT *p, BN_CTX *ctx); 37 | void EC_POINT_free(EC_POINT *point); 38 | 39 | point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); 40 | 41 | const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); 42 | int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); 43 | 44 | const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); 45 | int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); 46 | int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y); 47 | 48 | const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); 49 | int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); 50 | ]] 51 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/ecdsa.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | ECDSA_SIG *ECDSA_SIG_new(void); 7 | void ECDSA_SIG_free(ECDSA_SIG *sig); 8 | 9 | void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); 10 | int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); 11 | 12 | int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); 13 | ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); 14 | 15 | int EC_GROUP_order_bits(const EC_GROUP *group); 16 | ]] 17 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/err.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 5 | 6 | ffi.cdef [[ 7 | unsigned long ERR_peek_error(void); 8 | unsigned long ERR_peek_last_error(void); 9 | void ERR_clear_error(void); 10 | void ERR_error_string_n(unsigned long e, char *buf, size_t len); 11 | const char *ERR_lib_error_string(unsigned long e); 12 | const char *ERR_reason_error_string(unsigned long e); 13 | ]] 14 | 15 | if OPENSSL_3X then 16 | ffi.cdef [[ 17 | unsigned long ERR_get_error_all(const char **file, int *line, 18 | const char **func, 19 | const char **data, int *flags); 20 | unsigned long ERR_peek_last_error_all(const char **file, int *line, 21 | const char **func, 22 | const char **data, int *flags); 23 | ]] 24 | 25 | else 26 | ffi.cdef [[ 27 | unsigned long ERR_get_error_line(const char **file, int *line); 28 | unsigned long ERR_peek_last_error_line(const char **file, int *line); 29 | ]] 30 | end -------------------------------------------------------------------------------- /lib/resty/openssl/include/evp/cipher.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 5 | 6 | ffi.cdef [[ 7 | EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); 8 | // int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); 9 | void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c); 10 | 11 | int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); 12 | 13 | const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx); 14 | const EVP_CIPHER *EVP_get_cipherbyname(const char *name); 15 | int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); 16 | // int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, 17 | // int *outl, const unsigned char *in, int inl); 18 | // int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, 19 | // int *outl, const unsigned char *in, int inl); 20 | 21 | 22 | int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, 23 | const EVP_CIPHER *cipher, ENGINE *impl, 24 | const unsigned char *key, 25 | const unsigned char *iv, int enc); 26 | int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, 27 | int *outl, const unsigned char *in, int inl); 28 | int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, 29 | int *outl); 30 | 31 | // list functions 32 | typedef void* fake_openssl_cipher_list_fn(const EVP_CIPHER *ciph, const char *from, 33 | const char *to, void *x); 34 | //void EVP_CIPHER_do_all_sorted(fake_openssl_cipher_list_fn*, void *arg); 35 | void EVP_CIPHER_do_all_sorted(void (*fn) 36 | (const EVP_CIPHER *ciph, const char *from, 37 | const char *to, void *x), void *arg); 38 | 39 | int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, 40 | const unsigned char *salt, 41 | const unsigned char *data, int datal, int count, 42 | unsigned char *key, unsigned char *iv); 43 | 44 | ]] 45 | 46 | 47 | if OPENSSL_3X then 48 | require "resty.openssl.include.provider" 49 | 50 | ffi.cdef [[ 51 | int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx); 52 | int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx); 53 | int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx); 54 | 55 | int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher); 56 | 57 | const OSSL_PROVIDER *EVP_CIPHER_get0_provider(const EVP_CIPHER *cipher); 58 | EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, 59 | const char *properties); 60 | 61 | typedef void* fake_openssl_cipher_provided_list_fn(EVP_CIPHER *cipher, void *arg); 62 | void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx, 63 | fake_openssl_cipher_provided_list_fn*, 64 | void *arg); 65 | // int EVP_CIPHER_up_ref(EVP_CIPHER *cipher); 66 | // void EVP_CIPHER_free(EVP_CIPHER *cipher); 67 | 68 | const char *EVP_CIPHER_get0_name(const EVP_CIPHER *cipher); 69 | 70 | int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]); 71 | const OSSL_PARAM *EVP_CIPHER_CTX_settable_params(EVP_CIPHER_CTX *ctx); 72 | int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]); 73 | const OSSL_PARAM *EVP_CIPHER_CTX_gettable_params(EVP_CIPHER_CTX *ctx); 74 | ]] 75 | else 76 | ffi.cdef [[ 77 | int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); 78 | int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); 79 | int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); 80 | 81 | int EVP_CIPHER_nid(const EVP_CIPHER *cipher); 82 | ]] 83 | end 84 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/evp/mac.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.provider" 5 | 6 | ffi.cdef [[ 7 | typedef struct evp_mac_st EVP_MAC; 8 | typedef struct evp_mac_ctx_st EVP_MAC_CTX; 9 | 10 | EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac); 11 | void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx); 12 | 13 | const OSSL_PROVIDER *EVP_MAC_get0_provider(const EVP_MAC *mac); 14 | EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, 15 | const char *properties); 16 | 17 | int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen, 18 | const OSSL_PARAM params[]); 19 | int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen); 20 | int EVP_MAC_final(EVP_MAC_CTX *ctx, 21 | unsigned char *out, size_t *outl, size_t outsize); 22 | 23 | size_t EVP_MAC_CTX_get_mac_size(EVP_MAC_CTX *ctx); 24 | 25 | typedef void* fake_openssl_mac_provided_list_fn(EVP_MAC *mac, void *arg); 26 | void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx, 27 | fake_openssl_mac_provided_list_fn*, 28 | void *arg); 29 | // int EVP_MAC_up_ref(EVP_MAC *mac); 30 | void EVP_MAC_free(EVP_MAC *mac); 31 | 32 | const char *EVP_MAC_get0_name(const EVP_MAC *mac); 33 | 34 | int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[]); 35 | const OSSL_PARAM *EVP_MAC_CTX_settable_params(EVP_MAC_CTX *ctx); 36 | int EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[]); 37 | const OSSL_PARAM *EVP_MAC_CTX_gettable_params(EVP_MAC_CTX *ctx); 38 | ]] -------------------------------------------------------------------------------- /lib/resty/openssl/include/evp/md.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 5 | 6 | ffi.cdef [[ 7 | int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, 8 | ENGINE *impl); 9 | int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, 10 | size_t cnt); 11 | int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, 12 | unsigned int *s); 13 | const EVP_MD *EVP_get_digestbyname(const char *name); 14 | int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, 15 | size_t cnt); 16 | int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, 17 | unsigned int *s); 18 | 19 | const EVP_MD *EVP_md_null(void); 20 | 21 | EVP_MD_CTX *EVP_MD_CTX_new(void); 22 | void EVP_MD_CTX_free(EVP_MD_CTX *ctx); 23 | 24 | typedef void* fake_openssl_md_list_fn(const EVP_MD *ciph, const char *from, 25 | const char *to, void *x); 26 | void EVP_MD_do_all_sorted(fake_openssl_md_list_fn*, void *arg); 27 | 28 | const EVP_MD *EVP_get_digestbyname(const char *name); 29 | ]] 30 | 31 | if OPENSSL_3X then 32 | require "resty.openssl.include.provider" 33 | 34 | ffi.cdef [[ 35 | int EVP_MD_get_size(const EVP_MD *md); 36 | int EVP_MD_get_type(const EVP_MD *md); 37 | const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md); 38 | 39 | EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, 40 | const char *properties); 41 | 42 | typedef void* fake_openssl_md_provided_list_fn(EVP_MD *md, void *arg); 43 | void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx, 44 | fake_openssl_md_provided_list_fn*, 45 | void *arg); 46 | // int EVP_MD_up_ref(EVP_MD *md); 47 | void EVP_MD_free(EVP_MD *md); 48 | 49 | const char *EVP_MD_get0_name(const EVP_MD *md); 50 | 51 | int EVP_MD_CTX_set_params(EVP_MD_CTX *ctx, const OSSL_PARAM params[]); 52 | const OSSL_PARAM *EVP_MD_CTX_settable_params(EVP_MD_CTX *ctx); 53 | int EVP_MD_CTX_get_params(EVP_MD_CTX *ctx, OSSL_PARAM params[]); 54 | const OSSL_PARAM *EVP_MD_CTX_gettable_params(EVP_MD_CTX *ctx); 55 | ]] 56 | else 57 | ffi.cdef [[ 58 | int EVP_MD_size(const EVP_MD *md); 59 | int EVP_MD_type(const EVP_MD *md); 60 | ]] 61 | end 62 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/hmac.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.evp" 5 | 6 | ffi.cdef [[ 7 | int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, 8 | const EVP_MD *md, ENGINE *impl); 9 | 10 | int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, 11 | size_t len); 12 | int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, 13 | unsigned int *len); 14 | 15 | HMAC_CTX *HMAC_CTX_new(void); 16 | void HMAC_CTX_free(HMAC_CTX *ctx); 17 | ]] 18 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/objects.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); 7 | ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name); 8 | int OBJ_txt2nid(const char *s); 9 | const char *OBJ_nid2sn(int n); 10 | int OBJ_ln2nid(const char *s); 11 | int OBJ_sn2nid(const char *s); 12 | const char *OBJ_nid2ln(int n); 13 | const char *OBJ_nid2sn(int n); 14 | int OBJ_obj2nid(const ASN1_OBJECT *o); 15 | const ASN1_OBJECT *OBJ_nid2obj(int n); 16 | int OBJ_create(const char *oid, const char *sn, const char *ln); 17 | 18 | int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); 19 | ]] 20 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/ossl_typ.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | ffi.cdef( 4 | [[ 5 | typedef struct rsa_st RSA; 6 | typedef struct evp_pkey_st EVP_PKEY; 7 | typedef struct bignum_st BIGNUM; 8 | typedef struct bn_gencb_st BN_GENCB; 9 | typedef struct bignum_ctx BN_CTX; 10 | typedef struct bio_st BIO; 11 | typedef struct evp_cipher_st EVP_CIPHER; 12 | typedef struct evp_md_ctx_st EVP_MD_CTX; 13 | typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; 14 | typedef struct evp_md_st EVP_MD; 15 | typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; 16 | typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; 17 | typedef struct engine_st ENGINE; 18 | typedef struct x509_st X509; 19 | typedef struct x509_attributes_st X509_ATTRIBUTE; 20 | typedef struct X509_extension_st X509_EXTENSION; 21 | typedef struct X509_name_st X509_NAME; 22 | typedef struct X509_name_entry_st X509_NAME_ENTRY; 23 | typedef struct X509_req_st X509_REQ; 24 | typedef struct X509_crl_st X509_CRL; 25 | typedef struct x509_store_st X509_STORE; 26 | typedef struct x509_store_ctx_st X509_STORE_CTX; 27 | typedef struct x509_purpose_st X509_PURPOSE; 28 | typedef struct v3_ext_ctx X509V3_CTX; 29 | typedef struct asn1_string_st ASN1_INTEGER; 30 | typedef struct asn1_string_st ASN1_ENUMERATED; 31 | typedef struct asn1_string_st ASN1_BIT_STRING; 32 | typedef struct asn1_string_st ASN1_OCTET_STRING; 33 | typedef struct asn1_string_st ASN1_PRINTABLESTRING; 34 | typedef struct asn1_string_st ASN1_T61STRING; 35 | typedef struct asn1_string_st ASN1_IA5STRING; 36 | typedef struct asn1_string_st ASN1_GENERALSTRING; 37 | typedef struct asn1_string_st ASN1_UNIVERSALSTRING; 38 | typedef struct asn1_string_st ASN1_BMPSTRING; 39 | typedef struct asn1_string_st ASN1_UTCTIME; 40 | typedef struct asn1_string_st ASN1_TIME; 41 | typedef struct asn1_string_st ASN1_GENERALIZEDTIME; 42 | typedef struct asn1_string_st ASN1_VISIBLESTRING; 43 | typedef struct asn1_string_st ASN1_UTF8STRING; 44 | typedef struct asn1_string_st ASN1_STRING; 45 | typedef struct asn1_object_st ASN1_OBJECT; 46 | typedef struct conf_st CONF; 47 | typedef struct conf_method_st CONF_METHOD; 48 | typedef int ASN1_BOOLEAN; 49 | typedef int ASN1_NULL; 50 | typedef struct ec_key_st EC_KEY; 51 | typedef struct ec_method_st EC_METHOD; 52 | typedef struct ec_point_st EC_POINT; 53 | typedef struct ec_group_st EC_GROUP; 54 | typedef struct rsa_meth_st RSA_METHOD; 55 | // typedef struct evp_keymgmt_st EVP_KEYMGMT; 56 | // typedef struct crypto_ex_data_st CRYPTO_EX_DATA; 57 | // typedef struct bn_mont_ctx_st BN_MONT_CTX; 58 | // typedef struct bn_blinding_st BN_BLINDING; 59 | // crypto.h 60 | // typedef void CRYPTO_RWLOCK; 61 | typedef struct hmac_ctx_st HMAC_CTX; 62 | typedef struct x509_revoked_st X509_REVOKED; 63 | typedef struct dh_st DH; 64 | typedef struct PKCS12_st PKCS12; 65 | typedef struct ssl_st SSL; 66 | typedef struct ssl_ctx_st SSL_CTX; 67 | typedef struct evp_kdf_st EVP_KDF; 68 | typedef struct evp_kdf_ctx_st EVP_KDF_CTX; 69 | typedef struct ossl_lib_ctx_st OSSL_LIB_CTX; 70 | typedef struct ECDSA_SIG_st ECDSA_SIG; 71 | ]]) 72 | 73 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/param.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | typedef struct ossl_param_st { 7 | const char *key; /* the name of the parameter */ 8 | unsigned int data_type; /* declare what kind of content is in buffer */ 9 | void *data; /* value being passed in or out */ 10 | size_t data_size; /* data size */ 11 | size_t return_size; /* returned content size */ 12 | } OSSL_PARAM; 13 | 14 | OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf); 15 | OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf); 16 | OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf, 17 | size_t bsize); 18 | // OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf); 19 | OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf, 20 | size_t bsize); 21 | OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf, 22 | size_t bsize); 23 | OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf, 24 | size_t bsize); 25 | OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf, 26 | size_t bsize); 27 | OSSL_PARAM OSSL_PARAM_construct_end(void); 28 | 29 | int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val); 30 | int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val); 31 | int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val); 32 | int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val); 33 | // int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val); 34 | // int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val); 35 | 36 | int OSSL_PARAM_set_int(OSSL_PARAM *p, int val); 37 | int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val); 38 | int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val); 39 | int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val); 40 | int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val); 41 | int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val); 42 | int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val); 43 | int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val); 44 | // int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val); 45 | // int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val); 46 | 47 | int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val); 48 | int OSSL_PARAM_set_double(OSSL_PARAM *p, double val); 49 | 50 | int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val); 51 | int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val); 52 | 53 | int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len); 54 | int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val); 55 | 56 | int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len, 57 | size_t *used_len); 58 | int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, size_t len); 59 | 60 | int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val); 61 | int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val); 62 | 63 | int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val, 64 | size_t *used_len); 65 | int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val, 66 | size_t used_len); 67 | 68 | int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val); 69 | int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val, 70 | size_t *used_len); 71 | ]] 72 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/pem.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | 4 | require "resty.openssl.include.ossl_typ" 5 | 6 | ffi.cdef [[ 7 | // all pem_password_cb* has been modified to pem_password_cb to avoid a table overflow issue 8 | typedef int (*pem_password_cb)(char *buf, int size, int rwflag, void *userdata); 9 | EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, 10 | // the following signature has been modified to avoid ffi.cast 11 | pem_password_cb cb, const char *u); 12 | // pem_password_cb *cb, void *u); 13 | EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, 14 | // the following signature has been modified to avoid ffi.cast 15 | pem_password_cb cb, const char *u); 16 | // pem_password_cb *cb, void *u); 17 | int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, 18 | unsigned char *kstr, int klen, 19 | pem_password_cb *cb, void *u); 20 | int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x); 21 | 22 | RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x, 23 | // the following signature has been modified to avoid ffi.cast 24 | pem_password_cb cb, const char *u); 25 | // pem_password_cb *cb, void *u); 26 | RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x, 27 | // the following signature has been modified to avoid ffi.cast 28 | pem_password_cb cb, const char *u); 29 | // pem_password_cb *cb, void *u); 30 | int PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc, 31 | unsigned char *kstr, int klen, 32 | pem_password_cb *cb, void *u); 33 | int PEM_write_bio_RSAPublicKey(BIO *bp, RSA *x); 34 | 35 | X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x, pem_password_cb cb, void *u); 36 | int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x); 37 | 38 | X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x, pem_password_cb cb, void *u); 39 | int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x); 40 | 41 | X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb cb, void *u); 42 | int PEM_write_bio_X509(BIO *bp, X509 *x); 43 | 44 | DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb cb, void *u); 45 | int PEM_write_bio_DHparams(BIO *bp, DH *x); 46 | 47 | EC_GROUP *PEM_read_bio_ECPKParameters(BIO *bp, EC_GROUP **x, pem_password_cb cb, void *u); 48 | int PEM_write_bio_ECPKParameters(BIO *bp, const EC_GROUP *x); 49 | 50 | ]] 51 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/pkcs12.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.stack" 5 | 6 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 7 | 8 | ffi.cdef [[ 9 | // hack by changing char* to const char* here 10 | PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, 11 | OPENSSL_STACK *ca, // STACK_OF(X509) 12 | int nid_key, int nid_cert, int iter, int mac_iter, int keytype); 13 | 14 | int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, 15 | OPENSSL_STACK **ca); // STACK_OF(X509) **ca); 16 | 17 | void PKCS12_free(PKCS12 *p12); 18 | int i2d_PKCS12_bio(BIO *bp, PKCS12 *a); 19 | PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **a); 20 | ]] 21 | 22 | if OPENSSL_3X then 23 | ffi.cdef [[ 24 | PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, 25 | X509 *cert, 26 | OPENSSL_STACK *ca, // STACK_OF(X509) 27 | int nid_key, int nid_cert, 28 | int iter, int mac_iter, int keytype, 29 | OSSL_LIB_CTX *ctx, const char *propq); 30 | ]] 31 | end 32 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/provider.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.param" 5 | 6 | ffi.cdef [[ 7 | typedef struct ossl_provider_st OSSL_PROVIDER; 8 | typedef struct ossl_lib_ctx_st OSSL_LIB_CTX; 9 | 10 | void OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, 11 | const char *path); 12 | 13 | 14 | OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name); 15 | OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name); 16 | int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov); 17 | int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name); 18 | 19 | const OSSL_PARAM *OSSL_PROVIDER_gettable_params(OSSL_PROVIDER *prov); 20 | int OSSL_PROVIDER_get_params(OSSL_PROVIDER *prov, OSSL_PARAM params[]); 21 | 22 | // int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, 23 | // ossl_provider_init_fn *init_fn); 24 | 25 | const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov); 26 | int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov); 27 | ]] 28 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/rand.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 5 | 6 | if OPENSSL_3X then 7 | ffi.cdef [[ 8 | int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, 9 | unsigned int strength); 10 | int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, 11 | unsigned int strength); 12 | ]] 13 | else 14 | ffi.cdef [[ 15 | int RAND_bytes(unsigned char *buf, int num); 16 | int RAND_priv_bytes(unsigned char *buf, int num); 17 | ]] 18 | end 19 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/rsa.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | 5 | ffi.cdef [[ 6 | RSA *RSA_new(void); 7 | void RSA_free(RSA *r); 8 | 9 | void RSA_get0_key(const RSA *r, 10 | const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); 11 | void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); 12 | void RSA_get0_crt_params(const RSA *r, 13 | const BIGNUM **dmp1, const BIGNUM **dmq1, 14 | const BIGNUM **iqmp); 15 | 16 | int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); 17 | int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); 18 | int RSA_set0_crt_params(RSA *r,BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); 19 | struct rsa_st; 20 | ]] 21 | 22 | return { 23 | paddings = { 24 | RSA_PKCS1_PADDING = 1, 25 | RSA_SSLV23_PADDING = 2, 26 | RSA_NO_PADDING = 3, 27 | RSA_PKCS1_OAEP_PADDING = 4, 28 | RSA_X931_PADDING = 5, 29 | RSA_PKCS1_PSS_PADDING = 6, 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/ssl.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "resty.openssl.include.ossl_typ" 5 | require "resty.openssl.include.stack" 6 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 7 | 8 | ffi.cdef [[ 9 | // SSL_METHOD 10 | typedef struct ssl_method_st SSL_METHOD; 11 | // const SSL_METHOD *TLS_method(void); 12 | const SSL_METHOD *TLS_server_method(void); 13 | 14 | // SSL_CIPHER 15 | typedef struct ssl_cipher_st SSL_CIPHER; 16 | const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher); 17 | SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl); 18 | 19 | SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); 20 | void SSL_CTX_free(SSL_CTX *a); 21 | 22 | // SSL_SESSION 23 | typedef struct ssl_session_st SSL_SESSION; 24 | SSL_SESSION *SSL_get_session(const SSL *ssl); 25 | long SSL_SESSION_set_timeout(SSL_SESSION *s, long t); 26 | long SSL_SESSION_get_timeout(const SSL_SESSION *s); 27 | 28 | typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl, 29 | const unsigned char **out, 30 | unsigned char *outlen, 31 | const unsigned char *in, 32 | unsigned int inlen, 33 | void *arg); 34 | void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, 35 | SSL_CTX_alpn_select_cb_func cb, 36 | void *arg); 37 | 38 | int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, 39 | const unsigned char *server, 40 | unsigned int server_len, 41 | const unsigned char *client, 42 | unsigned int client_len); 43 | 44 | SSL *SSL_new(SSL_CTX *ctx); 45 | void SSL_free(SSL *ssl); 46 | 47 | int SSL_set_cipher_list(SSL *ssl, const char *str); 48 | int SSL_set_ciphersuites(SSL *s, const char *str); 49 | 50 | long SSL_set_options(SSL *ssl, long options); 51 | long SSL_clear_options(SSL *ssl, long options); 52 | long SSL_get_options(SSL *ssl); 53 | 54 | /*STACK_OF(SSL_CIPHER)*/ OPENSSL_STACK *SSL_get_ciphers(const SSL *ssl); 55 | // /*STACK_OF(SSL_CIPHER)*/ OPENSSL_STACK *SSL_CTX_get_ciphers(const SSL_CTX *ctx); 56 | OPENSSL_STACK *SSL_get_peer_cert_chain(const SSL *ssl); 57 | 58 | typedef int (*verify_callback)(int preverify_ok, X509_STORE_CTX *x509_ctx); 59 | void SSL_set_verify(SSL *s, int mode, 60 | int (*verify_callback)(int, X509_STORE_CTX *)); 61 | 62 | int SSL_add_client_CA(SSL *ssl, X509 *cacert); 63 | 64 | long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); 65 | ]] 66 | 67 | if OPENSSL_3X then 68 | ffi.cdef [[ 69 | X509 *SSL_get1_peer_certificate(const SSL *ssl); 70 | ]] 71 | else 72 | ffi.cdef [[ 73 | X509 *SSL_get_peer_certificate(const SSL *ssl); 74 | ]] 75 | end 76 | 77 | local SSL_CTRL_SET_MIN_PROTO_VERSION = 123 78 | local SSL_CTRL_SET_MAX_PROTO_VERSION = 124 79 | 80 | local SSL_set_min_proto_version = function(ctx, version) 81 | return C.SSL_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nil) 82 | end 83 | 84 | local SSL_set_max_proto_version = function(ctx, version) 85 | return C.SSL_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nil) 86 | end 87 | 88 | return { 89 | SSL_set_min_proto_version = SSL_set_min_proto_version, 90 | SSL_set_max_proto_version = SSL_set_max_proto_version, 91 | } 92 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/stack.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | The OpenSSL stack library. Note `safestack` is not usable here in ffi because 3 | those symbols are eaten after preprocessing. 4 | Instead, we should do a Lua land type checking by having a nested field indicating 5 | which type of cdata its ctx holds. 6 | ]] 7 | 8 | local ffi = require "ffi" 9 | 10 | require "resty.openssl.include.ossl_typ" 11 | 12 | ffi.cdef [[ 13 | typedef char *OPENSSL_STRING; 14 | typedef struct stack_st OPENSSL_STACK; 15 | 16 | OPENSSL_STACK *OPENSSL_sk_new_null(void); 17 | int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data); 18 | void OPENSSL_sk_pop_free(OPENSSL_STACK *st, void (*func) (void *)); 19 | int OPENSSL_sk_num(const OPENSSL_STACK *); 20 | void *OPENSSL_sk_value(const OPENSSL_STACK *, int); 21 | OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st); 22 | void OPENSSL_sk_free(OPENSSL_STACK *); 23 | // void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc); 24 | 25 | typedef void (*OPENSSL_sk_freefunc)(void *); 26 | typedef void *(*OPENSSL_sk_copyfunc)(const void *); 27 | OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *, 28 | OPENSSL_sk_copyfunc c, 29 | OPENSSL_sk_freefunc f); 30 | ]] 31 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/altname.lua: -------------------------------------------------------------------------------- 1 | local GEN_OTHERNAME = 0 2 | local GEN_EMAIL = 1 3 | local GEN_DNS = 2 4 | local GEN_X400 = 3 5 | local GEN_DIRNAME = 4 6 | local GEN_EDIPARTY = 5 7 | local GEN_URI = 6 8 | local GEN_IPADD = 7 9 | local GEN_RID = 8 10 | 11 | local default_types = { 12 | OtherName = GEN_OTHERNAME, -- otherName 13 | RFC822Name = GEN_EMAIL, -- email 14 | RFC822 = GEN_EMAIL, 15 | Email = GEN_EMAIL, 16 | DNSName = GEN_DNS, -- dns 17 | DNS = GEN_DNS, 18 | X400 = GEN_X400, -- x400 19 | DirName = GEN_DIRNAME, -- dirName 20 | EdiParty = GEN_EDIPARTY, -- EdiParty 21 | UniformResourceIdentifier = GEN_URI, -- uri 22 | URI = GEN_URI, 23 | IPAddress = GEN_IPADD, -- ipaddr 24 | IP = GEN_IPADD, 25 | RID = GEN_RID, -- rid 26 | } 27 | 28 | local literals = { 29 | [GEN_OTHERNAME] = "OtherName", 30 | [GEN_EMAIL] = "email", 31 | [GEN_DNS] = "DNS", 32 | [GEN_X400] = "X400", 33 | [GEN_DIRNAME] = "DirName", 34 | [GEN_EDIPARTY] = "EdiParty", 35 | [GEN_URI] = "URI", 36 | [GEN_IPADD] = "IP", 37 | [GEN_RID] = "RID", 38 | } 39 | 40 | local types = {} 41 | for t, gid in pairs(default_types) do 42 | types[t:lower()] = gid 43 | types[t] = gid 44 | end 45 | 46 | return { 47 | types = types, 48 | literals = literals, 49 | } -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/crl.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.evp" 5 | require "resty.openssl.include.objects" 6 | require "resty.openssl.include.x509" 7 | require "resty.openssl.include.stack" 8 | 9 | local asn1_macro = require "resty.openssl.include.asn1" 10 | 11 | asn1_macro.declare_asn1_functions("X509_CRL", asn1_macro.has_new_ex) 12 | 13 | ffi.cdef [[ 14 | X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); 15 | int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); 16 | int X509_CRL_set_version(X509_CRL *x, long version); 17 | 18 | int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); 19 | X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); 20 | int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos); 21 | // void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx); 22 | 23 | int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); 24 | int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); 25 | 26 | int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); 27 | X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); 28 | int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); 29 | 30 | int X509_CRL_print(BIO *bio, X509_CRL *crl); 31 | 32 | int X509_CRL_get0_by_serial(X509_CRL *crl, 33 | X509_REVOKED **ret, ASN1_INTEGER *serial); 34 | // int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); 35 | 36 | //STACK_OF(X509_REVOKED) 37 | OPENSSL_STACK *X509_CRL_get_REVOKED(X509_CRL *crl); 38 | 39 | int X509_CRL_get0_by_serial(X509_CRL *crl, 40 | X509_REVOKED **ret, ASN1_INTEGER *serial); 41 | 42 | int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); 43 | int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); 44 | /*const*/ ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); 45 | /*const*/ ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); 46 | long X509_CRL_get_version(const X509_CRL *crl); 47 | 48 | X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); 49 | 50 | int X509_CRL_get_signature_nid(const X509_CRL *crl); 51 | ]] 52 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/csr.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.evp" 5 | require "resty.openssl.include.objects" 6 | require "resty.openssl.include.x509" 7 | require "resty.openssl.include.stack" 8 | 9 | local asn1_macro = require "resty.openssl.include.asn1" 10 | 11 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 12 | 13 | asn1_macro.declare_asn1_functions("X509_REQ", asn1_macro.has_new_ex) 14 | 15 | ffi.cdef [[ 16 | int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); 17 | 18 | EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); 19 | int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); 20 | 21 | int X509_REQ_set_version(X509_REQ *x, long version); 22 | 23 | int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); 24 | X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); 25 | int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos); 26 | 27 | int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); 28 | void X509_ATTRIBUTE_free(X509_ATTRIBUTE *a); 29 | // int X509_REQ_get_attr_count(const X509_REQ *req); 30 | // int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); 31 | X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); 32 | 33 | // int *X509_REQ_get_extension_nids(void); 34 | 35 | int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); 36 | int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); 37 | 38 | int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); 39 | X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); 40 | 41 | // STACK_OF(X509_EXTENSION) 42 | OPENSSL_STACK *X509_REQ_get_extensions(X509_REQ *req); 43 | // STACK_OF(X509_EXTENSION) 44 | int X509_REQ_add_extensions(X509_REQ *req, OPENSSL_STACK *exts); 45 | 46 | int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k); 47 | 48 | X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req); 49 | long X509_REQ_get_version(const X509_REQ *req); 50 | 51 | int X509_REQ_get_signature_nid(const X509_REQ *crl); 52 | ]] 53 | 54 | if OPENSSL_3X then 55 | ffi.cdef [[ 56 | // int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *pkey, OSSL_LIB_CTX *libctx, 57 | // const char *propq); 58 | ]] 59 | end 60 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/extension.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.x509v3" 5 | require "resty.openssl.include.x509" 6 | local asn1_macro = require "resty.openssl.include.asn1" 7 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 8 | 9 | asn1_macro.declare_asn1_functions("X509_EXTENSION") 10 | 11 | if OPENSSL_3X then 12 | ffi.cdef [[ 13 | struct v3_ext_ctx { 14 | int flags; 15 | X509 *issuer_cert; 16 | X509 *subject_cert; 17 | X509_REQ *subject_req; 18 | X509_CRL *crl; 19 | /*X509V3_CONF_METHOD*/ void *db_meth; 20 | void *db; 21 | EVP_PKEY *issuer_pkey; 22 | }; 23 | 24 | int X509V3_set_issuer_pkey(X509V3_CTX *ctx, EVP_PKEY *pkey); 25 | ]] 26 | 27 | else 28 | ffi.cdef [[ 29 | struct v3_ext_ctx { 30 | int flags; 31 | X509 *issuer_cert; 32 | X509 *subject_cert; 33 | X509_REQ *subject_req; 34 | X509_CRL *crl; 35 | /*X509V3_CONF_METHOD*/ void *db_meth; 36 | void *db; 37 | }; 38 | ]] 39 | end 40 | 41 | ffi.cdef [[ 42 | int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data); 43 | int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj); 44 | ]] -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/init.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.bio" 5 | require "resty.openssl.include.pem" 6 | require "resty.openssl.include.stack" 7 | local asn1_macro = require "resty.openssl.include.asn1" 8 | 9 | asn1_macro.declare_asn1_functions("X509", asn1_macro.has_new_ex) 10 | 11 | ffi.cdef [[ 12 | int i2d_X509_bio(BIO *bp, X509 *x509); 13 | X509 *d2i_X509_bio(BIO *bp, X509 **x509); 14 | 15 | // STACK_OF(X509) 16 | OPENSSL_STACK *X509_chain_up_ref(OPENSSL_STACK *chain); 17 | 18 | int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); 19 | int X509_verify(X509 *a, EVP_PKEY *r); 20 | 21 | ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj); 22 | 23 | int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); 24 | X509_EXTENSION *X509_get_ext(const X509 *x, int loc); 25 | int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); 26 | void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx); 27 | 28 | int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); 29 | int X509_EXTENSION_get_critical(const X509_EXTENSION *ex); 30 | ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); 31 | ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); 32 | X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); 33 | X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, 34 | int nid, int crit, 35 | ASN1_OCTET_STRING *data); 36 | 37 | // needed by pkey 38 | EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); 39 | EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); 40 | int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); 41 | int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); 42 | 43 | EVP_PKEY *X509_get_pubkey(X509 *x); 44 | int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); 45 | int X509_set_version(X509 *x, long version); 46 | int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); 47 | 48 | X509_NAME *X509_get_subject_name(const X509 *a); 49 | int X509_set_subject_name(X509 *x, X509_NAME *name); 50 | X509_NAME *X509_get_issuer_name(const X509 *a); 51 | int X509_set_issuer_name(X509 *x, X509_NAME *name); 52 | 53 | int X509_pubkey_digest(const X509 *data, const EVP_MD *type, 54 | unsigned char *md, unsigned int *len); 55 | int X509_digest(const X509 *data, const EVP_MD *type, 56 | unsigned char *md, unsigned int *len); 57 | 58 | const char *X509_verify_cert_error_string(long n); 59 | int X509_verify_cert(X509_STORE_CTX *ctx); 60 | 61 | int X509_get_signature_nid(const X509 *x); 62 | 63 | unsigned char *X509_alias_get0(X509 *x, int *len); 64 | // unsigned char *X509_keyid_get0(X509 *x, int *len); 65 | int X509_check_private_key(X509 *x, EVP_PKEY *k); 66 | 67 | int X509_up_ref(X509 *a); 68 | 69 | int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); 70 | int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); 71 | /*const*/ ASN1_TIME *X509_get0_notBefore(const X509 *x); 72 | /*const*/ ASN1_TIME *X509_get0_notAfter(const X509 *x); 73 | long X509_get_version(const X509 *x); 74 | const ASN1_INTEGER *X509_get0_serialNumber(X509 *x); 75 | 76 | X509_EXTENSION *X509_delete_ext(X509 *x, int loc); 77 | ]] 78 | -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/name.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.asn1" 5 | require "resty.openssl.include.objects" 6 | local asn1_macro = require "resty.openssl.include.asn1" 7 | 8 | asn1_macro.declare_asn1_functions("X509_NAME") 9 | 10 | ffi.cdef [[ 11 | int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, 12 | const unsigned char *bytes, int len, int loc, 13 | int set); 14 | 15 | int X509_NAME_entry_count(const X509_NAME *name); 16 | X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); 17 | ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne); 18 | ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne); 19 | int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, 20 | int lastpos); 21 | ]] -------------------------------------------------------------------------------- /lib/resty/openssl/include/x509/revoked.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.ossl_typ" 4 | require "resty.openssl.include.asn1" 5 | require "resty.openssl.include.objects" 6 | local asn1_macro = require "resty.openssl.include.asn1" 7 | 8 | asn1_macro.declare_asn1_functions("X509_REVOKED") 9 | 10 | ffi.cdef [[ 11 | int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); 12 | int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); 13 | int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); 14 | 15 | const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *r); 16 | const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *r); 17 | ]] -------------------------------------------------------------------------------- /lib/resty/openssl/mac.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_str = ffi.string 5 | 6 | require "resty.openssl.include.evp.mac" 7 | local param_lib = require "resty.openssl.param" 8 | local ctx_lib = require "resty.openssl.ctx" 9 | local ctypes = require "resty.openssl.auxiliary.ctypes" 10 | local format_error = require("resty.openssl.err").format_error 11 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 12 | 13 | local _M = {} 14 | local mt = {__index = _M} 15 | 16 | local mac_ctx_ptr_ct = ffi.typeof('EVP_MAC_CTX*') 17 | local param_types = { 18 | cipher = param_lib.OSSL_PARAM_UTF8_STRING, 19 | digest = param_lib.OSSL_PARAM_UTF8_STRING, 20 | } 21 | local params = {} 22 | 23 | function _M.new(key, typ, cipher, digest, properties) 24 | if not OPENSSL_3X then 25 | return false, "EVP_MAC is only supported from OpenSSL 3.0" 26 | end 27 | 28 | local algo = C.EVP_MAC_fetch(ctx_lib.get_libctx(), typ, properties) 29 | if algo == nil then 30 | return nil, format_error(string.format("mac.new: invalid mac type \"%s\"", typ)) 31 | end 32 | ffi_gc(algo, C.EVP_MAC_free) 33 | 34 | local ctx = C.EVP_MAC_CTX_new(algo) 35 | if ctx == nil then 36 | return nil, "mac.new: failed to create EVP_MAC_CTX" 37 | end 38 | ffi_gc(ctx, C.EVP_MAC_CTX_free) 39 | 40 | params.digest = digest 41 | params.cipher = cipher 42 | local p = param_lib.construct(params, 2, param_types) 43 | 44 | local keyl = #key 45 | local code = C.EVP_MAC_init(ctx, key, keyl, p) 46 | if code ~= 1 then 47 | return nil, format_error(string.format("mac.new: invalid cipher or digest type")) 48 | end 49 | 50 | local md_size = C.EVP_MAC_CTX_get_mac_size(ctx) 51 | 52 | return setmetatable({ 53 | ctx = ctx, 54 | algo = algo, 55 | buf = ctypes.uchar_array(md_size), 56 | buf_size = md_size, 57 | _reset = function() return C.EVP_MAC_init(ctx, key, keyl, p) end, 58 | }, mt), nil 59 | end 60 | 61 | function _M.istype(l) 62 | return l and l.ctx and ffi.istype(mac_ctx_ptr_ct, l.ctx) 63 | end 64 | 65 | function _M:get_provider_name() 66 | local p = C.EVP_MAC_get0_provider(self.algo) 67 | if p == nil then 68 | return nil 69 | end 70 | return ffi_str(C.OSSL_PROVIDER_get0_name(p)) 71 | end 72 | 73 | _M.settable_params, _M.set_params, _M.gettable_params, _M.get_param = param_lib.get_params_func("EVP_MAC_CTX") 74 | 75 | function _M:update(...) 76 | for _, s in ipairs({...}) do 77 | if C.EVP_MAC_update(self.ctx, s, #s) ~= 1 then 78 | return false, format_error("mac:update") 79 | end 80 | end 81 | return true, nil 82 | end 83 | 84 | function _M:final(s) 85 | if s then 86 | if C.EVP_MAC_update(self.ctx, s, #s) ~= 1 then 87 | return false, format_error("mac:final") 88 | end 89 | end 90 | 91 | local length = ctypes.ptr_of_size_t() 92 | if C.EVP_MAC_final(self.ctx, self.buf, length, self.buf_size) ~= 1 then 93 | return nil, format_error("mac:final: EVP_MAC_final") 94 | end 95 | return ffi_str(self.buf, length[0]) 96 | end 97 | 98 | function _M:reset() 99 | local code = self._reset() 100 | if code ~= 1 then 101 | return false, format_error("mac:reset") 102 | end 103 | 104 | return true 105 | end 106 | 107 | return _M 108 | -------------------------------------------------------------------------------- /lib/resty/openssl/objects.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_str = ffi.string 4 | local ffi_sizeof = ffi.sizeof 5 | 6 | require "resty.openssl.include.objects" 7 | require "resty.openssl.include.err" 8 | 9 | local buf = ffi.new('char[?]', 100) 10 | 11 | local function obj2table(obj) 12 | local nid = C.OBJ_obj2nid(obj) 13 | 14 | local len = C.OBJ_obj2txt(buf, ffi_sizeof(buf), obj, 1) 15 | local oid = ffi_str(buf, len) 16 | 17 | return { 18 | id = oid, 19 | nid = nid, 20 | sn = ffi_str(C.OBJ_nid2sn(nid)), 21 | ln = ffi_str(C.OBJ_nid2ln(nid)), 22 | } 23 | end 24 | 25 | local function nid2table(nid) 26 | return obj2table(C.OBJ_nid2obj(nid)) 27 | end 28 | 29 | local function txt2nid(txt) 30 | if type(txt) ~= "string" then 31 | return nil, "objects.txt2nid: expect a string at #1" 32 | end 33 | local nid = C.OBJ_txt2nid(txt) 34 | if nid == 0 then 35 | -- clean up error occurs during OBJ_txt2nid 36 | C.ERR_clear_error() 37 | return nil, "objects.txt2nid: invalid NID text " .. txt 38 | end 39 | return nid 40 | end 41 | 42 | local function txtnid2nid(txt_nid) 43 | local nid 44 | if type(txt_nid) == "string" then 45 | nid = C.OBJ_txt2nid(txt_nid) 46 | if nid == 0 then 47 | -- clean up error occurs during OBJ_txt2nid 48 | C.ERR_clear_error() 49 | return nil, "objects.txtnid2nid: invalid NID text " .. txt_nid 50 | end 51 | elseif type(txt_nid) == "number" then 52 | nid = txt_nid 53 | else 54 | return nil, "objects.txtnid2nid: expect string or number at #1" 55 | end 56 | return nid 57 | end 58 | 59 | local function find_sigid_algs(nid) 60 | local out = ffi.new("int[1]") 61 | if C.OBJ_find_sigid_algs(nid, out, nil) == 0 then 62 | return 0, "objects.find_sigid_algs: invalid sigid " .. nid 63 | end 64 | return tonumber(out[0]) 65 | end 66 | 67 | return { 68 | obj2table = obj2table, 69 | nid2table = nid2table, 70 | txt2nid = txt2nid, 71 | txtnid2nid = txtnid2nid, 72 | find_sigid_algs = find_sigid_algs, 73 | create = C.OBJ_create, 74 | } 75 | -------------------------------------------------------------------------------- /lib/resty/openssl/rand.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_str = ffi.string 4 | 5 | require "resty.openssl.include.rand" 6 | local ctx_lib = require "resty.openssl.ctx" 7 | local ctypes = require "resty.openssl.auxiliary.ctypes" 8 | local format_error = require("resty.openssl.err").format_error 9 | local OPENSSL_3X = require("resty.openssl.version").OPENSSL_3X 10 | 11 | local buf 12 | local buf_size = 0 13 | local function bytes(length, private, strength) 14 | if type(length) ~= "number" then 15 | return nil, "rand.bytes: expect a number at #1" 16 | elseif strength and type(strength) ~= "number" then 17 | return nil, "rand.bytes: expect a number at #3" 18 | end 19 | -- generally we don't need manually reseed rng 20 | -- https://www.openssl.org/docs/man1.1.1/man3/RAND_seed.html 21 | 22 | -- initialize or resize buffer 23 | if not buf or buf_size < length then 24 | buf = ctypes.uchar_array(length) 25 | buf_size = length 26 | end 27 | 28 | local code 29 | if OPENSSL_3X then 30 | if private then 31 | code = C.RAND_priv_bytes_ex(ctx_lib.get_libctx(), buf, length, strength or 0) 32 | else 33 | code = C.RAND_bytes_ex(ctx_lib.get_libctx(), buf, length, strength or 0) 34 | end 35 | else 36 | if private then 37 | code = C.RAND_priv_bytes(buf, length) 38 | else 39 | code = C.RAND_bytes(buf, length) 40 | end 41 | end 42 | if code ~= 1 then 43 | return nil, format_error("rand.bytes", code) 44 | end 45 | 46 | return ffi_str(buf, length) 47 | end 48 | 49 | return { 50 | bytes = bytes, 51 | } 52 | -------------------------------------------------------------------------------- /lib/resty/openssl/rsa.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | local bn_lib = require "resty.openssl.bn" 5 | local format_error = require("resty.openssl.err").format_error 6 | 7 | local _M = {} 8 | 9 | _M.params = {"n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp"} 10 | 11 | local empty_table = {} 12 | local bn_ptrptr_ct = ffi.typeof("const BIGNUM *[1]") 13 | function _M.get_parameters(rsa_st) 14 | -- {"n", "e", "d", "p", "q", "dmp1", "dmq1", "iqmp"} 15 | return setmetatable(empty_table, { 16 | __index = function(_, k) 17 | local ptr, ret 18 | ptr = bn_ptrptr_ct() 19 | 20 | if k == 'n' then 21 | C.RSA_get0_key(rsa_st, ptr, nil, nil) 22 | elseif k == 'e' then 23 | C.RSA_get0_key(rsa_st, nil, ptr, nil) 24 | elseif k == 'd' then 25 | C.RSA_get0_key(rsa_st, nil, nil, ptr) 26 | elseif k == 'p' then 27 | C.RSA_get0_factors(rsa_st, ptr, nil) 28 | elseif k == 'q' then 29 | C.RSA_get0_factors(rsa_st, nil, ptr) 30 | elseif k == 'dmp1' then 31 | C.RSA_get0_crt_params(rsa_st, ptr, nil, nil) 32 | elseif k == 'dmq1' then 33 | C.RSA_get0_crt_params(rsa_st, nil, ptr, nil) 34 | elseif k == 'iqmp' then 35 | C.RSA_get0_crt_params(rsa_st, nil, nil, ptr) 36 | else 37 | return nil, "rsa.get_parameters: unknown parameter \"" .. k .. "\" for RSA key" 38 | end 39 | 40 | ret = ptr[0] 41 | 42 | if ret == nil then 43 | return nil 44 | end 45 | return bn_lib.dup(ret) 46 | end 47 | }), nil 48 | end 49 | 50 | local function dup_bn_value(v) 51 | if not bn_lib.istype(v) then 52 | return nil, "expect value to be a bn instance" 53 | end 54 | local bn = C.BN_dup(v.ctx) 55 | if bn == nil then 56 | return nil, "BN_dup() failed" 57 | end 58 | return bn 59 | end 60 | 61 | function _M.set_parameters(rsa_st, opts) 62 | local err 63 | local opts_bn = {} 64 | -- remember which parts of BNs has been added to rsa_st, they should be freed 65 | -- by RSA_free and we don't cleanup them on failure 66 | local cleanup_from_idx = 1 67 | -- dup input 68 | local do_set_key, do_set_factors, do_set_crt_params 69 | 70 | while true do -- luacheck: ignore 71 | for k, v in pairs(opts) do 72 | opts_bn[k], err = dup_bn_value(v) 73 | if err then 74 | -- luacheck: ignore 75 | err = "rsa.set_parameters: cannot process parameter \"" .. k .. "\":" .. err 76 | break 77 | end 78 | if k == "n" or k == "e" or k == "d" then 79 | do_set_key = true 80 | elseif k == "p" or k == "q" then 81 | do_set_factors = true 82 | elseif k == "dmp1" or k == "dmq1" or k == "iqmp" then 83 | do_set_crt_params = true 84 | end 85 | end 86 | 87 | -- "The values n and e must be non-NULL the first time this function is called on a given RSA object." 88 | -- thus we force to set them together 89 | local code 90 | if do_set_key then 91 | code = C.RSA_set0_key(rsa_st, opts_bn["n"], opts_bn["e"], opts_bn["d"]) 92 | if code == 0 then 93 | err = format_error("rsa.set_parameters: RSA_set0_key") 94 | break 95 | end 96 | end 97 | 98 | cleanup_from_idx = cleanup_from_idx + 3 99 | if do_set_factors then 100 | code = C.RSA_set0_factors(rsa_st, opts_bn["p"], opts_bn["q"]) 101 | if code == 0 then 102 | err = format_error("rsa.set_parameters: RSA_set0_factors") 103 | break 104 | end 105 | end 106 | 107 | cleanup_from_idx = cleanup_from_idx + 2 108 | if do_set_crt_params then 109 | code = C.RSA_set0_crt_params(rsa_st, opts_bn["dmp1"], opts_bn["dmq1"], opts_bn["iqmp"]) 110 | if code == 0 then 111 | err = format_error("rsa.set_parameters: RSA_set0_crt_params") 112 | break 113 | end 114 | end 115 | 116 | return true 117 | end 118 | 119 | for i, k in pairs(_M.params) do 120 | if i >= cleanup_from_idx then 121 | C.BN_free(opts_bn[k]) 122 | end 123 | end 124 | return false, err 125 | end 126 | 127 | return _M 128 | -------------------------------------------------------------------------------- /lib/resty/openssl/ssl_ctx.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local new_tab = table.new 4 | local char = string.char 5 | local concat = table.concat 6 | 7 | require "resty.openssl.include.ssl" 8 | 9 | local nginx_aux = require("resty.openssl.auxiliary.nginx") 10 | 11 | local _M = {} 12 | local mt = {__index = _M} 13 | 14 | local ssl_ctx_ptr_ct = ffi.typeof('SSL_CTX*') 15 | 16 | function _M.from_request() 17 | -- don't GC this 18 | local ctx, err = nginx_aux.get_req_ssl_ctx() 19 | if err ~= nil then 20 | return nil, err 21 | end 22 | 23 | return setmetatable({ 24 | ctx = ctx, 25 | -- the cdata is not manage by Lua, don't GC on Lua side 26 | _managed = false, 27 | -- this is the Server SSL session 28 | _server = true, 29 | }, mt) 30 | end 31 | 32 | function _M.from_socket(socket) 33 | if not socket then 34 | return nil, "expect a ngx.socket.tcp instance at #1" 35 | end 36 | -- don't GC this 37 | local ctx, err = nginx_aux.get_socket_ssl_ctx(socket) 38 | if err ~= nil then 39 | return nil, err 40 | end 41 | 42 | return setmetatable({ 43 | ctx = ctx, 44 | -- the cdata is not manage by Lua, don't GC on Lua side 45 | _managed = false, 46 | -- this is the client SSL session 47 | _server = false, 48 | }, mt) 49 | end 50 | 51 | function _M.istype(l) 52 | return l and l.ctx and ffi.istype(ssl_ctx_ptr_ct, l.ctx) 53 | end 54 | 55 | local function encode_alpn_wire(alpns) 56 | local ret = new_tab(#alpns*2, 0) 57 | for i, alpn in ipairs(alpns) do 58 | ret[i*2-1] = char(#alpn) 59 | ret[i*2] = alpn 60 | end 61 | 62 | return concat(ret, "") 63 | end 64 | 65 | function _M:set_alpns(alpns) 66 | if not self._server then 67 | return nil, "ssl_ctx:set_alpns is only supported on server side" 68 | end 69 | 70 | alpns = encode_alpn_wire(alpns) 71 | 72 | if self._alpn_select_cb then 73 | self._alpn_select_cb:free() 74 | end 75 | 76 | local alpn_select_cb = ffi.cast("SSL_CTX_alpn_select_cb_func", function(_, out, outlen, client, client_len) 77 | local code = ffi.C.SSL_select_next_proto( 78 | ffi.cast("unsigned char **", out), outlen, 79 | alpns, #alpns, 80 | client, client_len) 81 | if code ~= 1 then -- OPENSSL_NPN_NEGOTIATED 82 | return 3 -- SSL_TLSEXT_ERR_NOACK 83 | end 84 | return 0 -- SSL_TLSEXT_ERR_OK 85 | end) 86 | 87 | C.SSL_CTX_set_alpn_select_cb(self.ctx, alpn_select_cb, nil) 88 | -- store the reference to avoid it being GC'ed 89 | self._alpn_select_cb = alpn_select_cb 90 | 91 | return true 92 | end 93 | 94 | 95 | return _M -------------------------------------------------------------------------------- /lib/resty/openssl/version.lua: -------------------------------------------------------------------------------- 1 | -- https://github.com/GUI/lua-openssl-ffi/blob/master/lib/openssl-ffi/version.lua 2 | local ffi = require "ffi" 3 | local C = ffi.C 4 | local ffi_str = ffi.string 5 | local log_debug = require "resty.openssl.auxiliary.compat".log_debug 6 | 7 | local libcrypto_name 8 | local lib_patterns = { 9 | "%s", "%s.so.3", "%s.so.1.1", "%s.so.1.0" 10 | } 11 | 12 | local function load_library() 13 | for _, pattern in ipairs(lib_patterns) do 14 | -- true: load to global namespae 15 | local pok, _ = pcall(ffi.load, string.format(pattern, "crypto"), true) 16 | if pok then 17 | libcrypto_name = string.format(pattern, "crypto") 18 | ffi.load(string.format(pattern, "ssl"), true) 19 | 20 | log_debug("loaded crypto library: ", libcrypto_name) 21 | return libcrypto_name 22 | end 23 | end 24 | 25 | return false, "unable to load crypto library" 26 | end 27 | 28 | ffi.cdef[[ 29 | // >= 1.1 30 | unsigned long OpenSSL_version_num(); 31 | const char *OpenSSL_version(int t); 32 | // >= 3.0 33 | const char *OPENSSL_info(int t); 34 | ]] 35 | 36 | local version_func, info_func 37 | local types_table = { 38 | VERSION = 0, 39 | CFLAGS = 1, 40 | BUILT_ON = 2, 41 | PLATFORM = 3, 42 | DIR = 4, 43 | ENGINES_DIR = 5, 44 | VERSION_STRING = 6, 45 | FULL_VERSION_STRING = 7, 46 | MODULES_DIR = 8, 47 | CPU_INFO = 9, 48 | } 49 | 50 | local get_version = function() 51 | local num = C.OpenSSL_version_num() 52 | version_func = C.OpenSSL_version 53 | return num 54 | end 55 | 56 | local ok, version_num = pcall(get_version) 57 | if not ok then 58 | ok, version_num = pcall(load_library) 59 | if ok then 60 | -- try again 61 | ok, version_num = pcall(get_version) 62 | end 63 | end 64 | 65 | if not ok then 66 | error(string.format("OpenSSL has encountered an error: %s; is OpenSSL library loaded?", 67 | tostring(version_num))) 68 | elseif type(version_num) == 'number' and version_num < 0x10101000 then 69 | error(string.format("OpenSSL version %s is not supported", tostring(version_num or 0))) 70 | elseif not version_num then 71 | error("Can not get OpenSSL version") 72 | end 73 | 74 | if version_num >= 0x30000000 then 75 | local info_table = { 76 | INFO_CONFIG_DIR = 1001, 77 | INFO_ENGINES_DIR = 1002, 78 | INFO_MODULES_DIR = 1003, 79 | INFO_DSO_EXTENSION = 1004, 80 | INFO_DIR_FILENAME_SEPARATOR = 1005, 81 | INFO_LIST_SEPARATOR = 1006, 82 | INFO_SEED_SOURCE = 1007, 83 | INFO_CPU_SETTINGS = 1008, 84 | } 85 | 86 | for k, v in pairs(info_table) do 87 | types_table[k] = v 88 | end 89 | 90 | info_func = C.OPENSSL_info 91 | else 92 | info_func = function(_) 93 | error(string.format("OPENSSL_info is not supported on %s", ffi_str(version_func(0)))) 94 | end 95 | end 96 | 97 | return setmetatable({ 98 | version_num = tonumber(version_num), 99 | version_text = ffi_str(version_func(0)), 100 | version = function(t) 101 | return ffi_str(version_func(t)) 102 | end, 103 | info = function(t) 104 | return ffi_str(info_func(t)) 105 | end, 106 | -- the following has implict upper bound of 4.x 107 | OPENSSL_30 = version_num >= 0x30000000 and version_num < 0x30100000, 108 | OPENSSL_3X = version_num >= 0x30000000 and version_num < 0x40000000, 109 | OPENSSL_111 = version_num >= 0x10101000 and version_num < 0x10200000, 110 | }, { 111 | __index = types_table, 112 | }) 113 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/chain.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | 5 | local stack_lib = require "resty.openssl.stack" 6 | local x509_lib = require "resty.openssl.x509" 7 | local format_error = require("resty.openssl.err").format_error 8 | 9 | local _M = {} 10 | 11 | local stack_ptr_ct = ffi.typeof("OPENSSL_STACK*") 12 | 13 | local STACK = "X509" 14 | local gc = stack_lib.gc_of(STACK) 15 | local new = stack_lib.new_of(STACK) 16 | local add = stack_lib.add_of(STACK) 17 | local mt = stack_lib.mt_of(STACK, x509_lib.dup, _M) 18 | 19 | function _M.new() 20 | local raw, err = new() 21 | if raw == nil then 22 | return nil, err 23 | end 24 | 25 | local self = setmetatable({ 26 | stack_of = STACK, 27 | ctx = raw, 28 | }, mt) 29 | 30 | return self, nil 31 | end 32 | 33 | function _M.istype(l) 34 | return l and l.ctx and ffi.istype(stack_ptr_ct, l.ctx) 35 | and l.stack_of and l.stack_of == STACK 36 | end 37 | 38 | function _M.dup(ctx) 39 | if ctx == nil or not ffi.istype(stack_ptr_ct, ctx) then 40 | return nil, "x509.chain.dup: expect a stack ctx at #1, got " .. type(ctx) 41 | end 42 | -- sk_X509_dup plus up ref for each X509 element 43 | local ctx = C.X509_chain_up_ref(ctx) 44 | if ctx == nil then 45 | return nil, "x509.chain.dup: X509_chain_up_ref() failed" 46 | end 47 | ffi_gc(ctx, gc) 48 | 49 | return setmetatable({ 50 | stack_of = STACK, 51 | ctx = ctx, 52 | }, mt) 53 | end 54 | 55 | function _M:add(x509) 56 | if not x509_lib.istype(x509) then 57 | return nil, "x509.chain:add: expect a x509 instance at #1" 58 | end 59 | 60 | local dup = C.X509_dup(x509.ctx) 61 | if dup == nil then 62 | return nil, format_error("x509.chain:add: X509_dup") 63 | end 64 | 65 | local _, err = add(self.ctx, dup) 66 | if err then 67 | C.X509_free(dup) 68 | return nil, err 69 | end 70 | 71 | return true 72 | end 73 | 74 | _M.all = stack_lib.all_func(mt) 75 | _M.each = mt.__ipairs 76 | _M.index = mt.__index 77 | _M.count = mt.__len 78 | 79 | return _M 80 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/extension/dist_points.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | require "resty.openssl.include.x509" 4 | require "resty.openssl.include.x509v3" 5 | local altname_lib = require "resty.openssl.x509.altname" 6 | local stack_lib = require "resty.openssl.stack" 7 | 8 | local _M = {} 9 | 10 | local stack_ptr_ct = ffi.typeof("OPENSSL_STACK*") 11 | 12 | local STACK = "DIST_POINT" 13 | local new = stack_lib.new_of(STACK) 14 | local dup = stack_lib.dup_of(STACK) 15 | 16 | -- TODO: return other attributes? 17 | local cdp_decode_fullname = function(ctx) 18 | return altname_lib.dup(ctx.distpoint.name.fullname) 19 | end 20 | 21 | local mt = stack_lib.mt_of(STACK, cdp_decode_fullname, _M) 22 | 23 | function _M.new() 24 | local ctx = new() 25 | if ctx == nil then 26 | return nil, "OPENSSL_sk_new_null() failed" 27 | end 28 | 29 | local self = setmetatable({ 30 | stack_of = STACK, 31 | ctx = ctx, 32 | _is_shallow_copy = false, 33 | }, mt) 34 | 35 | return self, nil 36 | end 37 | 38 | function _M.istype(l) 39 | return l and l.ctx and ffi.istype(stack_ptr_ct, l.ctx) 40 | and l.stack_of and l.stack_of == STACK 41 | end 42 | 43 | function _M.dup(ctx) 44 | if ctx == nil or not ffi.istype(stack_ptr_ct, ctx) then 45 | return nil, "expect a stack ctx at #1" 46 | end 47 | local dup_ctx, err = dup(ctx) 48 | if dup_ctx == nil then 49 | return nil, err 50 | end 51 | 52 | return setmetatable({ 53 | stack_of = STACK, 54 | ctx = dup_ctx, 55 | -- don't let lua gc the original stack to keep its elements 56 | _dupped_from = ctx, 57 | _is_shallow_copy = true, 58 | _elem_refs = {}, 59 | _elem_refs_idx = 1, 60 | }, mt), nil 61 | end 62 | 63 | _M.all = function(stack) 64 | local ret = {} 65 | local _next = mt.__ipairs(stack) 66 | while true do 67 | local i, e = _next() 68 | if i then 69 | ret[i] = e 70 | else 71 | break 72 | end 73 | end 74 | return ret 75 | end 76 | 77 | _M.each = mt.__ipairs 78 | _M.index = mt.__index 79 | _M.count = mt.__len 80 | 81 | return _M 82 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/extension/info_access.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_cast = ffi.cast 5 | 6 | require "resty.openssl.include.x509" 7 | require "resty.openssl.include.x509v3" 8 | require "resty.openssl.include.err" 9 | local altname_lib = require "resty.openssl.x509.altname" 10 | local stack_lib = require "resty.openssl.stack" 11 | 12 | local _M = {} 13 | 14 | local authority_info_access_ptr_ct = ffi.typeof("AUTHORITY_INFO_ACCESS*") 15 | 16 | local STACK = "ACCESS_DESCRIPTION" 17 | local new = stack_lib.new_of(STACK) 18 | local add = stack_lib.add_of(STACK) 19 | local dup = stack_lib.dup_of(STACK) 20 | 21 | local aia_decode = function(ctx) 22 | local nid = C.OBJ_obj2nid(ctx.method) 23 | local gn = altname_lib.gn_decode(ctx.location) 24 | return { nid, unpack(gn) } 25 | end 26 | 27 | local mt = stack_lib.mt_of(STACK, aia_decode, _M) 28 | local mt__pairs = mt.__pairs 29 | mt.__pairs = function(tbl) 30 | local f = mt__pairs(tbl) 31 | return function() 32 | local _, e = f() 33 | if not e then return end 34 | return unpack(e) 35 | end 36 | end 37 | 38 | function _M.new() 39 | local ctx = new() 40 | if ctx == nil then 41 | return nil, "OPENSSL_sk_new_null() failed" 42 | end 43 | local cast = ffi_cast("AUTHORITY_INFO_ACCESS*", ctx) 44 | 45 | local self = setmetatable({ 46 | ctx = ctx, 47 | cast = cast, 48 | _is_shallow_copy = false, 49 | }, mt) 50 | 51 | return self, nil 52 | end 53 | 54 | function _M.istype(l) 55 | return l and l.cast and ffi.istype(authority_info_access_ptr_ct, l.cast) 56 | end 57 | 58 | function _M.dup(ctx) 59 | if ctx == nil or not ffi.istype(authority_info_access_ptr_ct, ctx) then 60 | return nil, "expect a AUTHORITY_INFO_ACCESS* ctx at #1" 61 | end 62 | local dup_ctx, err = dup(ctx) 63 | if dup_ctx == nil then 64 | return nil, err 65 | end 66 | 67 | return setmetatable({ 68 | ctx = dup_ctx, 69 | cast = ffi_cast(authority_info_access_ptr_ct, dup_ctx), 70 | -- don't let lua gc the original stack to keep its elements 71 | _dupped_from = ctx, 72 | _is_shallow_copy = true, 73 | _elem_refs = {}, 74 | _elem_refs_idx = 1, 75 | }, mt), nil 76 | end 77 | 78 | function _M:add(nid, typ, value) 79 | -- the stack element stays with stack 80 | -- we shouldn't add gc handler if it's already been 81 | -- pushed to stack. instead, rely on the gc handler 82 | -- of the stack to release all memories 83 | local ad = C.ACCESS_DESCRIPTION_new() 84 | if ad == nil then 85 | return nil, "ACCESS_DESCRIPTION_new() failed" 86 | end 87 | 88 | -- C.ASN1_OBJECT_free(ad.method) 89 | 90 | local asn1 = C.OBJ_txt2obj(nid, 0) 91 | if asn1 == nil then 92 | C.ACCESS_DESCRIPTION_free(ad) 93 | -- clean up error occurs during OBJ_txt2* 94 | C.ERR_clear_error() 95 | return nil, "invalid NID text " .. (nid or "nil") 96 | end 97 | 98 | ad.method = asn1 99 | 100 | local err = altname_lib.gn_set(ad.location, typ, value) 101 | if err then 102 | C.ACCESS_DESCRIPTION_free(ad) 103 | return nil, err 104 | end 105 | 106 | local _, err = add(self.ctx, ad) 107 | if err then 108 | C.ACCESS_DESCRIPTION_free(ad) 109 | return nil, err 110 | end 111 | 112 | -- if the stack is duplicated, the gc handler is not pop_free 113 | -- handle the gc by ourselves 114 | if self._is_shallow_copy then 115 | ffi_gc(ad, C.ACCESS_DESCRIPTION_free) 116 | self._elem_refs[self._elem_refs_idx] = ad 117 | self._elem_refs_idx = self._elem_refs_idx + 1 118 | end 119 | return self 120 | end 121 | 122 | _M.all = function(stack) 123 | local ret = {} 124 | local _next = mt.__ipairs(stack) 125 | while true do 126 | local i, e = _next() 127 | if i then 128 | ret[i] = e 129 | else 130 | break 131 | end 132 | end 133 | return ret 134 | end 135 | 136 | _M.each = mt.__ipairs 137 | _M.index = mt.__index 138 | _M.count = mt.__len 139 | 140 | return _M 141 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/extensions.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | 5 | local stack_lib = require "resty.openssl.stack" 6 | local extension_lib = require "resty.openssl.x509.extension" 7 | local format_error = require("resty.openssl.err").format_error 8 | 9 | local _M = {} 10 | 11 | local stack_ptr_ct = ffi.typeof("OPENSSL_STACK*") 12 | 13 | local STACK = "X509_EXTENSION" 14 | local new = stack_lib.new_of(STACK) 15 | local add = stack_lib.add_of(STACK) 16 | local dup = stack_lib.dup_of(STACK) 17 | local mt = stack_lib.mt_of(STACK, extension_lib.dup, _M) 18 | 19 | function _M.new() 20 | local raw, err = new() 21 | if raw == nil then 22 | return nil, err 23 | end 24 | 25 | local self = setmetatable({ 26 | stack_of = STACK, 27 | ctx = raw, 28 | }, mt) 29 | 30 | return self, nil 31 | end 32 | 33 | function _M.istype(l) 34 | return l and l.ctx and ffi.istype(stack_ptr_ct, l.ctx) 35 | and l.stack_of and l.stack_of == STACK 36 | end 37 | 38 | function _M.dup(ctx) 39 | if ctx == nil or not ffi.istype(stack_ptr_ct, ctx) then 40 | return nil, "x509.extensions.dup: expect a stack ctx at #1, got " .. type(ctx) 41 | end 42 | 43 | local dup_ctx, err = dup(ctx) 44 | if dup_ctx == nil then 45 | return nil, err 46 | end 47 | 48 | return setmetatable({ 49 | stack_of = STACK, 50 | ctx = dup_ctx, 51 | -- don't let lua gc the original stack to keep its elements 52 | _dupped_from = ctx, 53 | _is_shallow_copy = true, 54 | _elem_refs = {}, 55 | _elem_refs_idx = 1, 56 | }, mt), nil 57 | end 58 | 59 | function _M:add(extension) 60 | if not extension_lib.istype(extension) then 61 | return nil, "expect a x509.extension instance at #1" 62 | end 63 | 64 | local dup = C.X509_EXTENSION_dup(extension.ctx) 65 | if dup == nil then 66 | return nil, format_error("extensions:add: X509_EXTENSION_dup") 67 | end 68 | 69 | local _, err = add(self.ctx, dup) 70 | if err then 71 | C.X509_EXTENSION_free(dup) 72 | return nil, err 73 | end 74 | 75 | -- if the stack is duplicated, the gc handler is not pop_free 76 | -- handle the gc by ourselves 77 | if self._is_shallow_copy then 78 | ffi_gc(dup, C.X509_EXTENSION_free) 79 | self._elem_refs[self._elem_refs_idx] = dup 80 | self._elem_refs_idx = self._elem_refs_idx + 1 81 | end 82 | 83 | return true 84 | end 85 | 86 | _M.all = stack_lib.all_func(mt) 87 | _M.each = mt.__ipairs 88 | _M.index = mt.__index 89 | _M.count = mt.__len 90 | 91 | return _M 92 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/name.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | local ffi_str = ffi.string 5 | 6 | require "resty.openssl.include.x509.name" 7 | require "resty.openssl.include.err" 8 | local objects_lib = require "resty.openssl.objects" 9 | local asn1_macro = require "resty.openssl.include.asn1" 10 | 11 | -- local MBSTRING_FLAG = 0x1000 12 | local MBSTRING_ASC = 0x1001 -- (MBSTRING_FLAG|1) 13 | 14 | local _M = {} 15 | 16 | local x509_name_ptr_ct = ffi.typeof("X509_NAME*") 17 | 18 | -- starts from 0 19 | local function value_at(ctx, i) 20 | local entry = C.X509_NAME_get_entry(ctx, i) 21 | local obj = C.X509_NAME_ENTRY_get_object(entry) 22 | local ret = objects_lib.obj2table(obj) 23 | 24 | local str = C.X509_NAME_ENTRY_get_data(entry) 25 | if str ~= nil then 26 | ret.blob = ffi_str(asn1_macro.ASN1_STRING_get0_data(str)) 27 | end 28 | 29 | return ret 30 | end 31 | 32 | local function iter(tbl) 33 | local i = 0 34 | local n = tonumber(C.X509_NAME_entry_count(tbl.ctx)) 35 | return function() 36 | i = i + 1 37 | if i <= n then 38 | local obj = value_at(tbl.ctx, i-1) 39 | return obj.sn or obj.ln or obj.id, obj 40 | end 41 | end 42 | end 43 | 44 | local mt = { 45 | __index = _M, 46 | __pairs = iter, 47 | __len = function(tbl) return tonumber(C.X509_NAME_entry_count(tbl.ctx)) end, 48 | } 49 | 50 | function _M.new() 51 | local ctx = C.X509_NAME_new() 52 | if ctx == nil then 53 | return nil, "x509.name.new: X509_NAME_new() failed" 54 | end 55 | ffi_gc(ctx, C.X509_NAME_free) 56 | 57 | local self = setmetatable({ 58 | ctx = ctx, 59 | }, mt) 60 | 61 | return self, nil 62 | end 63 | 64 | function _M.istype(l) 65 | return l and l.ctx and ffi.istype(x509_name_ptr_ct, l.ctx) 66 | end 67 | 68 | function _M.dup(ctx) 69 | if not ffi.istype(x509_name_ptr_ct, ctx) then 70 | return nil, "x509.name.dup: expect a x509.name ctx at #1, got " .. type(ctx) 71 | end 72 | local ctx = C.X509_NAME_dup(ctx) 73 | ffi_gc(ctx, C.X509_NAME_free) 74 | 75 | local self = setmetatable({ 76 | ctx = ctx, 77 | }, mt) 78 | 79 | return self, nil 80 | end 81 | 82 | function _M:add(nid, txt) 83 | local asn1 = C.OBJ_txt2obj(nid, 0) 84 | if asn1 == nil then 85 | -- clean up error occurs during OBJ_txt2* 86 | C.ERR_clear_error() 87 | return nil, "x509.name:add: invalid NID text " .. (nid or "nil") 88 | end 89 | 90 | local code = C.X509_NAME_add_entry_by_OBJ(self.ctx, asn1, MBSTRING_ASC, txt, #txt, -1, 0) 91 | C.ASN1_OBJECT_free(asn1) 92 | 93 | if code ~= 1 then 94 | return nil, "x509.name:add: X509_NAME_add_entry_by_OBJ() failed" 95 | end 96 | 97 | return self 98 | end 99 | 100 | function _M:find(nid, last_pos) 101 | local asn1 = C.OBJ_txt2obj(nid, 0) 102 | if asn1 == nil then 103 | -- clean up error occurs during OBJ_txt2* 104 | C.ERR_clear_error() 105 | return nil, nil, "x509.name:find: invalid NID text " .. (nid or "nil") 106 | end 107 | -- make 1-index array to 0-index 108 | last_pos = (last_pos or 0) - 1 109 | 110 | local pos = C.X509_NAME_get_index_by_OBJ(self.ctx, asn1, last_pos) 111 | if pos == -1 then 112 | return nil 113 | end 114 | 115 | C.ASN1_OBJECT_free(asn1) 116 | 117 | return value_at(self.ctx, pos), pos+1 118 | end 119 | 120 | -- fallback function to iterate if LUAJIT_ENABLE_LUA52COMPAT not enabled 121 | function _M:all() 122 | local ret = {} 123 | local _next = iter(self) 124 | while true do 125 | local k, obj = _next() 126 | if obj then 127 | ret[k] = obj 128 | else 129 | break 130 | end 131 | end 132 | return ret 133 | end 134 | 135 | function _M:each() 136 | return iter(self) 137 | end 138 | 139 | mt.__tostring = function(self) 140 | local values = {} 141 | local _next = iter(self) 142 | while true do 143 | local k, v = _next() 144 | if k then 145 | table.insert(values, k .. "=" .. v.blob) 146 | else 147 | break 148 | end 149 | end 150 | table.sort(values) 151 | return table.concat(values, "/") 152 | end 153 | 154 | _M.tostring = mt.__tostring 155 | 156 | return _M 157 | -------------------------------------------------------------------------------- /lib/resty/openssl/x509/revoked.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local ffi_gc = ffi.gc 4 | 5 | require "resty.openssl.include.x509.crl" 6 | require "resty.openssl.include.x509.revoked" 7 | local bn_lib = require("resty.openssl.bn") 8 | local format_error = require("resty.openssl.err").format_error 9 | 10 | local _M = {} 11 | local mt = { __index = _M } 12 | 13 | local x509_revoked_ptr_ct = ffi.typeof('X509_REVOKED*') 14 | 15 | local NID_crl_reason = C.OBJ_txt2nid("CRLReason") 16 | assert(NID_crl_reason > 0) 17 | 18 | --- Creates new instance of X509_REVOKED data 19 | -- @tparam bn|number sn Serial number as number or bn instance 20 | -- @tparam number time Revocation time 21 | -- @tparam number reason Revocation reason 22 | -- @treturn table instance of the module or nil 23 | -- @treturn[opt] string Returns optional error message in case of error 24 | function _M.new(sn, time, reason) 25 | --- only convert to bn if it is number 26 | if type(sn) == "number"then 27 | sn = bn_lib.new(sn) 28 | end 29 | if not bn_lib.istype(sn) then 30 | return nil, "x509.revoked.new: sn should be number or a bn instance" 31 | end 32 | 33 | if type(time) ~= "number" then 34 | return nil, "x509.revoked.new: expect a number at #2" 35 | end 36 | if type(reason) ~= "number" then 37 | return nil, "x509.revoked.new: expect a number at #3" 38 | end 39 | 40 | local ctx = C.X509_REVOKED_new() 41 | ffi_gc(ctx, C.X509_REVOKED_free) 42 | 43 | -- serial number 44 | local sn_asn1 = C.BN_to_ASN1_INTEGER(sn.ctx, nil) 45 | if sn_asn1 == nil then 46 | return nil, "x509.revoked.new: BN_to_ASN1_INTEGER() failed" 47 | end 48 | ffi_gc(sn_asn1, C.ASN1_INTEGER_free) 49 | 50 | if C.X509_REVOKED_set_serialNumber(ctx, sn_asn1) == 0 then 51 | return nil, format_error("x509.revoked.new: X509_REVOKED_set_serialNumber()") 52 | end 53 | 54 | -- time 55 | time = C.ASN1_TIME_set(nil, time) 56 | if time == nil then 57 | return nil, format_error("x509.revoked.new: ASN1_TIME_set()") 58 | end 59 | ffi_gc(time, C.ASN1_STRING_free) 60 | 61 | if C.X509_REVOKED_set_revocationDate(ctx, time) == 0 then 62 | return nil, format_error("x509.revoked.new: X509_REVOKED_set_revocationDate()") 63 | end 64 | 65 | -- reason 66 | local reason_asn1 = C.ASN1_ENUMERATED_new() 67 | if reason_asn1 == nil then 68 | return nil, "x509.revoked.new: ASN1_ENUMERATED_new() failed" 69 | end 70 | ffi_gc(reason_asn1, C.ASN1_ENUMERATED_free) 71 | 72 | local reason_ext = C.X509_EXTENSION_new() 73 | if reason_ext == nil then 74 | return nil, "x509.revoked.new: X509_EXTENSION_new() failed" 75 | end 76 | ffi_gc(reason_ext, C.X509_EXTENSION_free) 77 | 78 | if C.ASN1_ENUMERATED_set(reason_asn1, reason) == 0 then 79 | return nil, format_error("x509.revoked.new: ASN1_ENUMERATED_set()") 80 | end 81 | 82 | if C.X509_EXTENSION_set_data(reason_ext, reason_asn1) == 0 then 83 | return nil, format_error("x509.revoked.new: X509_EXTENSION_set_data()") 84 | end 85 | 86 | if C.X509_EXTENSION_set_object(reason_ext, C.OBJ_nid2obj(NID_crl_reason)) == 0 then 87 | return nil, format_error("x509.revoked.new: X509_EXTENSION_set_object()") 88 | end 89 | 90 | if C.X509_REVOKED_add_ext(ctx, reason_ext, 0) == 0 then 91 | return nil, format_error("x509.revoked.new: X509_EXTENSION_set_object()") 92 | end 93 | 94 | local self = setmetatable({ 95 | ctx = ctx, 96 | }, mt) 97 | 98 | return self, nil 99 | end 100 | 101 | --- Type check 102 | -- @tparam table Instance of revoked module 103 | -- @treturn boolean true if instance is instance of revoked module false otherwise 104 | function _M.istype(l) 105 | return l and l.ctx and ffi.istype(x509_revoked_ptr_ct, l.ctx) 106 | end 107 | 108 | return _M 109 | -------------------------------------------------------------------------------- /scripts/extension_struct.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | types = { 4 | "BASIC_CONSTRAINTS": { 5 | "ca": "ca_bool_int", 6 | "pathlen": "ASN1_INTEGER", 7 | }, 8 | } 9 | 10 | getter_conv_tmpl = { 11 | "ca_bool_int": "ctx.{k} == 0xFF", 12 | "ASN1_INTEGER": "tonumber(C.ASN1_INTEGER_get(ctx.{k}))", 13 | } 14 | 15 | setter_conv_tmpl = { 16 | "ca_bool_int": ''' 17 | toset.{k} = cfg_lower.{k} and 0xFF or 0''', 18 | "ASN1_INTEGER": ''' 19 | local {k} = cfg_lower.{k} and tonumber(cfg_lower.{k}) 20 | if {k} then 21 | C.ASN1_INTEGER_free(toset.{k}) 22 | 23 | local asn1 = C.ASN1_STRING_type_new({k}) 24 | if asn1 == nil then 25 | return false, format_error("x509:set_{type}: ASN1_STRING_type_new") 26 | end 27 | toset.{k} = asn1 28 | 29 | local code = C.ASN1_INTEGER_set(asn1, {k}) 30 | if code ~= 1 then 31 | return false, format_error("x509:set_{type}: ASN1_INTEGER_set", code) 32 | end 33 | end''' 34 | } 35 | 36 | c2t_assign_locals = ''' 37 | local {k} = {conv}''' 38 | 39 | c2t_return_table = ''' 40 | {k} = {k},''' 41 | 42 | c2t_return_partial = ''' 43 | elseif string.lower(name) == "{k}" then 44 | got = {k}''' 45 | 46 | c2t = ''' 47 | local ctx = ffi_cast("{type}*", got) 48 | {assign_locals} 49 | 50 | C.{type}_free(ctx) 51 | 52 | if not name or type(name) ~= "string" then 53 | got = {{ 54 | {return_table} 55 | }} 56 | {return_partial} 57 | end 58 | ''' 59 | 60 | t2c = ''' 61 | local cfg_lower = {{}} 62 | for k, v in pairs(toset) do 63 | cfg_lower[string.lower(k)] = v 64 | end 65 | 66 | toset = C.{type}_new() 67 | if toset == nil then 68 | return false, format_error("x509:set_{type}") 69 | end 70 | ffi_gc(toset, C.{type}_free) 71 | {set_members} 72 | ''' 73 | # getter 74 | def c_struct_to_table(name): 75 | t = types[name] 76 | return c2t.format( 77 | type=name, 78 | assign_locals="".join([ 79 | c2t_assign_locals.format( 80 | k=k, 81 | conv=getter_conv_tmpl[v].format(k=k) 82 | ) 83 | for k, v in t.items() 84 | ]), 85 | return_table="".join([ 86 | c2t_return_table.format(k=k) 87 | for k in t 88 | ]).lstrip("\n"), 89 | return_partial="".join([ 90 | c2t_return_partial.format(k=k) 91 | for k in t 92 | ]).lstrip("\n"), 93 | ) 94 | 95 | # setter 96 | def table_to_c_struct(name): 97 | t = types[name] 98 | return t2c.format( 99 | type=name, 100 | set_members="".join([ 101 | setter_conv_tmpl[v].format( 102 | k=k, 103 | type=name, 104 | ) 105 | for k, v in t.items() 106 | ]), 107 | ) -------------------------------------------------------------------------------- /scripts/find_unused_cdef.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import re 5 | import sys 6 | 7 | current_script_path = os.path.abspath(sys.argv[0]) 8 | 9 | def load_files(path): 10 | file_contents = {} 11 | for root, _, files in os.walk(path): 12 | for file in files: 13 | if file.endswith(".lua"): 14 | p = os.path.join(root.replace(path, ""), file).lstrip("/") 15 | with open(os.path.join(root, file)) as f: 16 | file_contents[p] = f.readlines() 17 | 18 | return file_contents 19 | 20 | token = "[a-zA-Z0-9_]" 21 | def find_cdefs(files): 22 | cdefs = { 23 | "funcs": {}, 24 | "types": {}, 25 | } 26 | 27 | for path, lines in files.items(): 28 | start = False 29 | for i in range(len(lines)): 30 | line = lines[i] 31 | if "ffi.cdef" in line: 32 | start = True 33 | elif "]]" in line and start: 34 | start = False 35 | 36 | if start: 37 | if re.findall("^\s*//", line): # comment 38 | continue 39 | 40 | func = re.findall(f"{token}+[\s\*]+({token}+)\(", line) 41 | if func: 42 | cdefs["funcs"][func[0]] = f"{path}:{i}" 43 | type_ = re.findall(f"typedef.*?({token}+);", line) 44 | if type_: 45 | cdefs["types"][type_[0]] = f"{path}:{i}" 46 | type_ = re.findall(f"}}\s*({token}+);", line) 47 | if type_: 48 | cdefs["types"][type_[0]] = f"{path}:{i}" 49 | 50 | return cdefs 51 | 52 | # those are dynamically called 53 | ignore_list = [ 54 | "OSSL_PARAM_(?:set|get)_", 55 | "PEM_read_bio_", 56 | "fake_openssl_", 57 | "(?:d2i|i2d)_(?:PUBKEY|PrivateKey)_bio", 58 | "_(?:gettable|settable)_params", 59 | "_(?:get|set)_params", 60 | "_do_all_(?:sorted|provided)", 61 | "_get0_name", 62 | ] 63 | 64 | def check_cdefs(files, cdef): 65 | unused = { 66 | "funcs": {}, 67 | "types": {}, 68 | } 69 | undefined = { 70 | "funcs": {}, 71 | "types": {}, 72 | } 73 | 74 | patterns = { 75 | "funcs": "C.%s[^a-zA-Z0-9_]", 76 | "types": "%s[^a-zA-Z0-9_]", 77 | } 78 | 79 | ignore_regex = "(?:%s)" % "|".join(ignore_list) 80 | 81 | for name, regex_pattern in patterns.items(): 82 | for token, path in cdef[name].items(): 83 | found = False 84 | for _, lines in files.items(): 85 | full_content = "".join(lines) 86 | if re.findall(regex_pattern % token, full_content): 87 | found = True 88 | break 89 | if not found and not re.findall(ignore_regex, token): 90 | unused[name][token] = path 91 | 92 | # TODO: find undefined 93 | 94 | return unused, undefined 95 | 96 | def display(unused, undefined): 97 | for name, tokens in unused.items(): 98 | if len(tokens) == 0: 99 | continue 100 | 101 | print(f"Unused {name} ({len(tokens)}):") 102 | for token, path in tokens.items(): 103 | print(f" {token} on {path}") 104 | 105 | for name, tokens in undefined.items(): 106 | if len(tokens) == 0: 107 | continue 108 | 109 | print(f"Undefined {name} ({len(tokens)}):") 110 | for token, path in tokens.items(): 111 | print(f" {token} on {path}") 112 | 113 | 114 | if __name__ == '__main__': 115 | files = load_files(os.path.join(os.path.dirname(current_script_path), "..", "lib")) 116 | cdefs = find_cdefs(files) 117 | display(*check_cdefs(files, cdefs)) -------------------------------------------------------------------------------- /scripts/opm_upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | cd $(dirname $(readlink -e $0))/../ 3 | 4 | start=$(grep -n "## resty.openssl" README.md | head -n1 | cut -d: -f1) 5 | end=$(grep -n "Copyright and License" README.md | tail -n1 | cut -d: -f1) 6 | start=$(( start + 1 )) 7 | end=$(( end - 1 )) 8 | 9 | 10 | cat README.md | sed "${start},${end}d" | \ 11 | sed -E "s/([+*])(.+)#/\1\2https:\/\/github.com\/fffonion\/lua-resty-openssl#/g" | \ 12 | sed "s/## resty.openssl/Due to the size limit of OPM, the full documentation can be viewed at [Github](https:\/\/github.com\/fffonion\/lua-resty-openssl\/blob\/master\/README.md)\n\n/" \ 13 | > README.opm.md 14 | 15 | mv README.opm.md README.md 16 | 17 | opm upload 18 | 19 | git checkout README.md -------------------------------------------------------------------------------- /scripts/prepare_new_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -v 2 | 3 | new_v=$1 4 | if [[ -z $1 ]]; then 5 | echo "Usage: $0 version" 6 | exit 1 7 | fi 8 | 9 | if [[ $(uname) == "Darwin" ]]; then 10 | SED=gsed 11 | else 12 | SED=sed 13 | fi 14 | 15 | git reset 16 | old_rockspec=$(ls *.rockspec -r1|grep -v dev|grep -v "$new_v"|head -n1) 17 | old_v=$(echo $old_rockspec | cut -d '-' -f4) 18 | if [[ -z "$old_v" ]]; then 19 | echo "Unknown old version" 20 | exit 1 21 | fi 22 | 23 | echo "Creating new release $new_v from $old_v" 24 | git branch -D release/${new_v} 25 | git checkout -b release/${new_v} 26 | 27 | # rockspec 28 | new_rockspec="${old_rockspec/$old_v/$new_v}" 29 | cp "$old_rockspec" "$new_rockspec" 30 | git rm "$old_rockspec" 31 | $SED -i "s/$old_v/$new_v/g" "$new_rockspec" 32 | git add "$new_rockspec" 33 | 34 | # file 35 | $SED -i "s/_VERSION = '$old_v'/_VERSION = '$new_v'/g" lib/resty/*.lua 36 | git add -u 37 | 38 | # changelog 39 | git commit -m "release: $new_v" 40 | git tag "$new_v" 41 | git-chglog --output CHANGELOG.md 42 | git add -u 43 | git tag -d "$new_v" 44 | git commit -m "release: $new_v" --amend 45 | 46 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | jinja2==3.1.6 2 | -------------------------------------------------------------------------------- /scripts/type_x509_crl.py: -------------------------------------------------------------------------------- 1 | defines = { 2 | "output": "../lib/resty/openssl/x509/crl.lua", 3 | "output_test": "../t/openssl/x509/crl.t", 4 | "type": "X509_CRL", 5 | "has_extension_accessor_by_nid": True, 6 | "extensions_in_struct":"crl.extensions", 7 | "has_sign_verify": True, 8 | "sample": "TrustAsiaEVTLSProCAG2.crl", 9 | "sample_signature_nid": 668, 10 | "sample_signature_name": "RSA-SHA256", 11 | "sample_signature_digest_name": "SHA256", 12 | "fields": 13 | [ 14 | { 15 | "field": "issuer_name", 16 | "type": "x509.name", 17 | "dup": True, 18 | "sample_printable": "C=CN/CN=TrustAsia EV TLS Pro CA G2/O=TrustAsia Technologies, Inc.", 19 | }, 20 | 21 | { 22 | "field": "last_update", 23 | "type": "number", 24 | "sample_printable": 1580684546, 25 | "set_converter": ''' 26 | toset = C.ASN1_TIME_set(nil, toset) 27 | ffi_gc(toset, C.ASN1_STRING_free) 28 | ''', 29 | "get_converter": ''' 30 | got = asn1_lib.asn1_to_unix(got) 31 | ''', 32 | }, 33 | 34 | { 35 | "field": "next_update", 36 | "type": "number", 37 | "sample_printable": 1581289346, 38 | "set_converter": ''' 39 | toset = C.ASN1_TIME_set(nil, toset) 40 | ffi_gc(toset, C.ASN1_STRING_free) 41 | ''', 42 | "get_converter": ''' 43 | got = asn1_lib.asn1_to_unix(got) 44 | ''', 45 | }, 46 | 47 | { 48 | "field": "version", 49 | "type": "number", 50 | "sample_printable": 2, 51 | "set_converter": 52 | ''' 53 | -- Note: this is defined by standards (X.509 et al) to be one less than the certificate version. 54 | -- So a version 3 certificate will return 2 and a version 1 certificate will return 0. 55 | toset = toset - 1 56 | ''', 57 | "get_converter": 58 | ''' 59 | got = tonumber(got) + 1 60 | ''', 61 | }, 62 | ] 63 | } -------------------------------------------------------------------------------- /scripts/type_x509_req.py: -------------------------------------------------------------------------------- 1 | defines = { 2 | "output": "../lib/resty/openssl/x509/csr.lua", 3 | "output_test": "../t/openssl/x509/csr.t", 4 | "type": "X509_REQ", 5 | "has_sign_verify": True, 6 | "sample": "test.csr", 7 | "sample_signature_nid": 65, 8 | "sample_signature_name": "RSA-SHA1", 9 | "sample_signature_digest_name": "SHA1", 10 | "fields": 11 | [ 12 | { 13 | "field": "subject_name", 14 | "type": "x509.name", 15 | "dup": True, 16 | "sample_printable": "C=US/CN=example.com/L=Los Angeles/O=SSL Support/OU=SSL Support/ST=California", 17 | }, 18 | 19 | { 20 | "field": "pubkey", 21 | "type": "pkey", 22 | "sample_printable": '''-----BEGIN PUBLIC KEY----- 23 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPOIBIoblSLFv/ifj8GD 24 | CNL5NhDX2JVUQKcWC19KtWYQg1HPnaGIy+Dj9tYSBw8T8xc9hbJ1TYGbBIMKfBUz 25 | KoTt5yLdVIM/HJm3m9ImvAbK7TYcx1U9TJEMxN6686whAUMBr4B7ql4VTXqu6TgD 26 | cdbcQ5wsPVOiFHJTTwgVwt7eVCBMFAkZn+qQz+WigM5HEp8KFrzwAK142H2ucuyf 27 | gGS4+XQSsUdwNWh9GPRZgRt3R2h5ymYkQB/cbg596alCquoizI6QCfwQx3or9Dg1 28 | f3rlwf8H5HIVH3hATGIr7GpbKka/JH2PYNGfi5KqsJssVQfu84m+5WXDB+90KHJE 29 | cwIDAQAB 30 | -----END PUBLIC KEY----- 31 | ''', 32 | }, 33 | 34 | { 35 | "field": "version", 36 | "type": "number", 37 | "sample_printable": 1, 38 | "test_fixture": "1", # override the automatic fixture 39 | "set_converter": 40 | ''' 41 | -- Note: this is defined by standards (X.509 et al) to be one less than the certificate version. 42 | -- So a version 3 certificate will return 2 and a version 1 certificate will return 0. 43 | toset = toset - 1 44 | ''', 45 | "get_converter": 46 | ''' 47 | got = tonumber(got) + 1 48 | ''', 49 | }, 50 | 51 | ################## extensions ###################### 52 | 53 | { 54 | "field": "subject_alt_name", 55 | "type": "x509.altname", 56 | "dup": True, 57 | "extension_nid": "subjectAltName", 58 | "sample_printable": 'DNS=example.com', 59 | "get_converter": ''' 60 | -- Note: here we only free the stack itself not elements 61 | -- since there seems no way to increase ref count for a GENERAL_NAME 62 | -- we left the elements referenced by the new-dup'ed stack 63 | local got_ref = got 64 | got = ffi_cast("GENERAL_NAMES*", got_ref) 65 | ffi_gc(got, stack_lib.gc_of("GENERAL_NAME"))''', 66 | }, 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /scripts/types_test.py: -------------------------------------------------------------------------------- 1 | tests = { 2 | "types": 3 | { 4 | "bn": { 5 | "new_from": "new(math.random(1, 2333333))", 6 | "print": "to_hex", 7 | }, 8 | "number": { 9 | "new_from": "ngx.time()", 10 | }, 11 | "pkey": { 12 | "new_from": "new()", 13 | "print": "to_PEM" 14 | }, 15 | "x509.name": { 16 | "new_from": "new():add('CN', 'earth.galaxy')", 17 | "print": "tostring", 18 | }, 19 | "x509.altname": { 20 | "new_from": "new():add('DNS', 'earth.galaxy')", 21 | "print": "tostring", 22 | }, 23 | 24 | }, 25 | } -------------------------------------------------------------------------------- /scripts/x509_autogen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from jinja2 import Environment, FileSystemLoader 4 | 5 | import re 6 | 7 | ANCHOR_START = '((?:--|#) START AUTO GENERATED CODE)' 8 | ANCHOR_END = '((?:--|#) END AUTO GENERATED CODE)' 9 | 10 | LUA_TYPES = ('number', 'string', 'table') 11 | 12 | data = { 13 | "x509": __import__("type_x509").defines, 14 | "x509.csr": __import__("type_x509_req").defines, 15 | "x509.crl": __import__("type_x509_crl").defines, 16 | } 17 | 18 | from types_test import tests 19 | 20 | fl = FileSystemLoader('templates') 21 | env = Environment(loader=fl) 22 | 23 | tmpl = { 24 | "output": env.get_template('x509_functions.j2'), 25 | "output_test": env.get_template('x509_tests.j2') 26 | } 27 | 28 | for k in tmpl: 29 | for modname in data: 30 | mod = data[modname] 31 | output = mod[k] 32 | ct = None 33 | with open(output, "r") as f: 34 | ct = f.read() 35 | 36 | test_idx = re.findall('TEST (\d+)(?!.+AUTOGEN)', ct) 37 | if test_idx: 38 | test_idx = max([int(i) for i in test_idx]) + 1 39 | else: 40 | test_idx = None 41 | 42 | repl = tmpl[k].render( 43 | module=mod, 44 | modname=modname, 45 | test_idx=test_idx, 46 | tests=tests, 47 | LUA_TYPES=LUA_TYPES, 48 | ) 49 | 50 | ct = re.sub( 51 | ANCHOR_START + '.+' + ANCHOR_END, 52 | '\g<1>\n' + repl + '\n\g<2>', 53 | ct, 54 | flags = re.DOTALL, 55 | ) 56 | 57 | open(output, 'w').write(ct) 58 | 59 | print("%-40s: wrote %d %s (%dl)" % ( 60 | output, 61 | len(re.findall("(?:_M\:|===)", ct)), 62 | "tests" if k == 'output_test' else 'functions', 63 | len(repl.split('\n'))) 64 | ) -------------------------------------------------------------------------------- /t/fixtures/TrustAsiaEVTLSProCAG2.crl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fffonion/lua-resty-openssl/e0f52762fef5c31532e60c7d58c7a6d9ae5a6905/t/fixtures/TrustAsiaEVTLSProCAG2.crl -------------------------------------------------------------------------------- /t/fixtures/badssl.com-client.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fffonion/lua-resty-openssl/e0f52762fef5c31532e60c7d58c7a6d9ae5a6905/t/fixtures/badssl.com-client.p12 -------------------------------------------------------------------------------- /t/fixtures/crl/crl.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIIC2jCBwwIBATANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQIDAJDQTENMAsGA1UE 3 | CgwES29uZzENMAsGA1UECwwES29uZzEbMBkGA1UEAwwSd3d3LnN1YmNhLmtvbmcu 4 | Y29tFw0yMzA2MDYwNzI3MDBaFw0zMzA2MDMwNzI3MDBaMBUwEwICIAEXDTIzMDYw 5 | NjA3MjcwMFqgMDAuMB8GA1UdIwQYMBaAFC8MH19JRurEt8xm/9IGkZIvDBurMAsG 6 | A1UdFAQEAgIgADANBgkqhkiG9w0BAQsFAAOCAgEAGX+Tvt+BDU6YUSVc7/bi7OBA 7 | KPEQvl/SXu06n3JmjyCRIWUPkB/QruqNHPpxImpvDzoqp/ScfKjB7jNaVqppdkcr 8 | yrCN11U26WPgtW6auHsWPOqVm94625+vecL9U+8R5WvjN2Hn8Kkn7EXefwskYleo 9 | tGDHeQMRuR3EHzaHu6Bbqn/UfYuTEEC2ZMg/LwGYaG8MBCg79ayAzsBeR4VPSszK 10 | CnKHa1CVgfggWQnNcIvkbBFpUAd6OWm6w+YUSA9hxAaEFqYlrOA4UHf/APE7Rnw3 11 | xokDissm9yqfVVi0fiVe/HXt6RE5FOayOgjKOfAAj10TogTC9bK0Q05t8Ud1OpEY 12 | 7YtFHtlBYuHWrmqm0FZBYwhxaFzDRcCRe45HuS6wCmMwb1Btr354kEOj/nSuq2Wq 13 | e248ZrTPNf/IXOGthB7FsL+bTOtrHl4l+tniZb+0i3FeeYUHoX+IRhPzWGHXYK9D 14 | PDn1QsggNvkXIMpdut8ifDwPXYFoXf5ZW8IAuC7G3zYrwsPFoQALheK4yyqHVaYb 15 | WMzuHmeVpxLxVv7zoJtpGPr8X2c2Yn25QtcGpqxcXxesL5g2+pJ2Uu3D7niVp3tM 16 | bqP3Nj88eJk1mFVOdRWwSICmp6ReJwTtAYacU5vTUjPdQNOOtht29YmbwyoemMvJ 17 | w9wdUeL9yrb5a98bNtI= 18 | -----END X509 CRL----- 19 | -------------------------------------------------------------------------------- /t/fixtures/crl/gen_certs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # run this script in t/fixtures/crl 4 | # 5 | # root ca 6 | mkdir -p rootca/newcerts 7 | touch rootca/index.txt 8 | echo 1000 > rootca/serial 9 | 10 | # root ca key 11 | openssl genrsa -out rootca.key.pem 4096 12 | chmod 400 rootca.key.pem 13 | 14 | # root ca cert 15 | openssl req -config rootca.cnf -key rootca.key.pem \ 16 | -new -x509 -days 3650 -sha256 -extensions v3_ca \ 17 | -out rootca.cert.pem \ 18 | -subj "/C=US/ST=CA/L=SF/O=Kong/OU=Kong/CN=www.rootca.kong.com" 19 | 20 | 21 | # sub ca 22 | mkdir -p subca/newcerts 23 | touch subca/index.txt 24 | echo 2000 > subca/serial 25 | echo 2000 > subca/crlnumber 26 | 27 | # sub ca key 28 | openssl genrsa -out subca.key.pem 4096 29 | chmod 400 subca.key.pem 30 | 31 | # sub ca csr 32 | openssl req -config subca.cnf -new -sha256 \ 33 | -key subca.key.pem -out subca.csr.pem \ 34 | -subj "/C=US/ST=CA/L=SF/O=Kong/OU=Kong/CN=www.subca.kong.com" 35 | 36 | # sub ca cert 37 | echo -e "y\ny\n" | openssl ca -config rootca.cnf -extensions v3_sub_ca \ 38 | -days 3650 -notext -md sha256 \ 39 | -in subca.csr.pem -out subca.cert.pem 40 | 41 | # ca chain 42 | #cat ca/sub/subca.cert.pem ca/root/root.cert.pem > chain.pem 43 | 44 | # leaf certs 45 | for name in valid revoked 46 | do 47 | openssl genrsa -out $name.key.pem 2048 48 | chmod 400 $name.key.pem 49 | 50 | openssl req -config subca.cnf -key subca.key.pem \ 51 | -new -sha256 -out $name.csr.pem \ 52 | -subj "/C=US/ST=CA/L=SF/O=Kong/OU=Kong/CN=www.$name.kong.com" 53 | 54 | echo -e "y\ny\n" | openssl ca -config subca.cnf -extensions usr_cert \ 55 | -days 3650 -notext -md sha256 \ 56 | -in $name.csr.pem -out $name.cert.pem 57 | done 58 | 59 | # revoke cert 60 | openssl ca -config subca.cnf -revoke revoked.cert.pem 61 | 62 | # generate crl file 63 | openssl ca -config subca.cnf -gencrl -out crl.pem -crldays 3650 64 | 65 | # remove unused files 66 | rm -rf rootca subca *.csr.pem 67 | -------------------------------------------------------------------------------- /t/fixtures/crl/revoked.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /t/fixtures/crl/revoked.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA9Ieaw7RFz9+I8WTKFS8QYzIkduMdh0bYWkDn0M51t74U1YtC 3 | NDXaaFRRe7F/SvvP4vsJXTEJWdz6+RjwAtkZwXLUjjIGsHU+sLdlHGAwpnWz12gU 4 | p+Y+LBNWbkbvmcUV7BfVTzOzbaZi5fNA3AzUUXBvLPOYj8qFpGeU8ZSGEZiS9wAh 5 | yulFPnl8AxYKFqiuTWTIYLa2v/KT395QIcTqcQNpllRmvzQcBX14wTAqrukC3bfA 6 | lS/pGu1XE/utx/PkJAgHaxo3oHbirTp9aPGRce/dgUH4/NopuyEQvcaykLC+V75P 7 | JyUuPP7DD8UgXs8amBVibL4hbjlIQOLAqonBFQIDAQABAoIBAQDxioF1jzzmeQfs 8 | aoKzKiol0gHy7aTdWz2a6UITH91oAnrR9R0QNaHoLGHQrSPwDYzryM0XILj76yx9 9 | ogRyy8CFNciALSouY6HpLT7TKLDlvJ5IyKaesu/22aMmiyth2Swuadxqv8cdKJ3I 10 | RuBqfMG9MDKhVH3+iy43l5moh+1mskEddAIYEMMcb3HW4CQqb7FDi1EIqJcZNxlY 11 | V7o6t0VLUTgiauWTvXisv33Ozga/3vh4PzBvVpSCgn8AE3n+j06pp/wYsuYqeWU4 12 | eHreCN9Qh4NL2A9nN197mK98/JrujB0yuBJ/VCJfUKO5uydkgHzLnGsAYachppMe 13 | heGQkU6BAoGBAP5u6WXDgnhtA4ZyuvRxF+r8FzFDOKNw6E/QH55g8d/z2zQwrcQb 14 | o5BDFLxXeXKlIshy3aphxX8Y1LkFjm9d8+JRJG6ffRbXuKsC+K6CMmaW1vOQ180p 15 | Y/OPp0GLgpxA9fimo+EYhpWbdQlDTZUzfzBp1hu8UkP0VZu4XFSml0fPAoGBAPYJ 16 | FLYo/Oa1Kv0BSgVH2AZPax7Rl0I/7NWG4e1IaT/hawKzlypM3pMvZSana7gcGccr 17 | fGjG8GjliFm2R03H/GldfhXRoO3MCPF9FvWpW5ZRhCU2SSlsrj6SxG1KpCqkG2ft 18 | QSHI3f0H1mZdXXiRh3Z4jkb0c87IrCpMcasSjT3bAoGAY/75MeqV83h8wzGCMqHk 19 | EZGEF/NgZjPwybV1R8y4Ixl3FFrxYDqwnPkQRDlo3Nr0Aa3LWrRUZ3A94n3Bjhlx 20 | yYe0dtmt0vVzeZqQXB2Fa3ZrAozxk4tp4gaaaJNJANozEceEbuoxssjHRZ2y9ymn 21 | GkLuSDZKarSzlKDvgMF8gVcCgYEA3n1NxoEAWp1gd5Uv2+ChQOuWwjLk5xspz9p+ 22 | +nXt/7+YZsQDIlSLPmywuyjRZ5e50/vGMHYet61CBWapynPcFWhfedms/v3w5Hir 23 | R5JUaXXj20bhGF3YoGtWyEKkfI8U3YGW0bd0z7nDr6Qkv8BS0NaqSw4Kn+emkUW5 24 | 0Osg4NsCgYEAxOhcGIseH8e0K7YSsB8sRSOK01p0wTRpMhQ8GVsf4S4Za292B2Wl 25 | f2ZIFEj9IrTEwp14s2lOeeSpSMHYndWfHOTua0DSaKP6j0Dl2G3VlbZJsprDqRWX 26 | qA0vZ1ZucVFBe3GWtCaO7uQprQbk0NcerqmEdexY2vzGvUNuoQszuRo= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /t/fixtures/crl/rootca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | NehSHV5LPjYikoZm1oig/DEFjAPWQpgPVowG 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /t/fixtures/crl/rootca.cnf: -------------------------------------------------------------------------------- 1 | # OpenSSL root CA configuration file. 2 | # Copy to `/root/ca/openssl.cnf`. 3 | 4 | [ ca ] 5 | # `man ca` 6 | default_ca = CA_default 7 | 8 | [ CA_default ] 9 | # Directory and file locations. 10 | dir = ./rootca 11 | new_certs_dir = $dir/newcerts 12 | database = $dir/index.txt 13 | serial = $dir/serial 14 | RANDFILE = $dir/.rand 15 | 16 | # The root key and root certificate. 17 | private_key = rootca.key.pem 18 | certificate = rootca.cert.pem 19 | 20 | # SHA-1 is deprecated, so use SHA-2 instead. 21 | default_md = sha256 22 | 23 | name_opt = ca_default 24 | cert_opt = ca_default 25 | default_days = 365 26 | preserve = no 27 | policy = policy_strict 28 | 29 | [ policy_strict ] 30 | # The root CA should only sign intermediate certificates that match. 31 | # See the POLICY FORMAT section of `man subName = match 32 | stateOrProvinceName = match 33 | organizationName = match 34 | organizationalUnitName = optional 35 | commonName = supplied 36 | emailAddress = optional 37 | 38 | [ policy_loose ] 39 | # Allow the intermediate CA to sign a more diverse range of certificates. 40 | # See the POLICY FORMAT section of the `ca` man page. 41 | countryName = optional 42 | stateOrProvinceName = optional 43 | localityName = optional 44 | organizationName = optional 45 | organizationalUnitName = optional 46 | commonName = supplied 47 | emailAddress = optional 48 | 49 | [ req ] 50 | # Options for the `req` tool (`man req`). 51 | default_bits = 2048 52 | distinguished_name = req_distinguished_name 53 | string_mask = utf8only 54 | 55 | # SHA-1 is deprecated, so use SHA-2 instead. 56 | default_md = sha256 57 | 58 | # Extension to add when the -x509 option is used. 59 | x509_extensions = v3_ca 60 | 61 | [ req_distinguished_name ] 62 | # See . 63 | countryName = Country Name (2 letter code) 64 | stateOrProvinceName = State or Province Name 65 | localityName = Locality Name 66 | 0.organizationName = Organization Name 67 | organizationalUnitName = Organizational Unit Name 68 | commonName = Common Name 69 | emailAddress = Email Address 70 | 71 | # Optionally, specify some defaults. 72 | countryName_default = GB 73 | stateOrProvinceName_default = England 74 | localityName_default = 75 | 0.organizationName_default = Alice Ltd 76 | organizationalUnitName_default = 77 | emailAddress_default = 78 | 79 | [ v3_ca ] 80 | # Extensions for a typical CA (`man x509v3_config`). 81 | subjectKeyIdentifier = hash 82 | authorityKeyIdentifier = keyid:always,issuer 83 | basicConstraints = critical, CA:true 84 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 85 | 86 | [ v3_sub_ca ] 87 | # Extensions for a typical intermediate CA (`man x509v3_config`). 88 | subjectKeyIdentifier = hash 89 | authorityKeyIdentifier = keyid:always,issuer 90 | basicConstraints = critical, CA:true, pathlen:0 91 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 92 | -------------------------------------------------------------------------------- /t/fixtures/crl/rootca.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /t/fixtures/crl/subca.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFjTCCA3WgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMx 3 | CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjENMAsGA1UECgwES29uZzENMAsGA1UE 4 | CwwES29uZzEcMBoGA1UEAwwTd3d3LnJvb3RjYS5rb25nLmNvbTAeFw0yMzA2MDYw 5 | NzI2NTlaFw0zMzA2MDMwNzI2NTlaMEgxCzAJBgNVBAgMAkNBMQ0wCwYDVQQKDARL 6 | b25nMQ0wCwYDVQQLDARLb25nMRswGQYDVQQDDBJ3d3cuc3ViY2Eua29uZy5jb20w 7 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMTeKyEAH44OVBGWdthO69 8 | iQoEwn5SoII0isBTG7ogwla4ryHG34pI/RGAHss2kT8WyFS5k/Xp1mrwDkdqHa7+ 9 | vvJcS/qSY1R8BACbc1IVPxYGCNyzebhNOqy0uE8vexGdUQKRQYSrk8d9DFHcO78W 10 | rBiIYfqg5le6wVnO4fHRH/4YqR+Sr2qibAilnMxIgZuV9LTQKlYC8FhyVN4mZ/Kc 11 | MqINyKu8bmy7nmXCqyqSfYCCbzLs6pCwJxpQW+cwerF5XOTdupeNaV1+jt2+Jkc1 12 | bXtc7mu5Qkux5FkTdsIwF49CNCljqKXsrwKr2AnR23dNtH1ZJU1L4RS4IHdz2u1R 13 | P6qUGs1YKYzPdkt9cNiOqIfLqOiRPwrgGjamOiJnsiVRlDrfvFvtM4fm4hw5iwZH 14 | oC/zjeW3RO/WCuBpZtH+Q1I4gZEQ7RJBqTDqSGlVqxM0apKgEvIVvr5LPDsQBxk8 15 | IGH1k7P7Fd0FwaUKyYScDAb0FIUEbjKBR07c7K9l5IYP0HA1kXOoCL90oklblefU 16 | YclBR6OuufUaIOX41oiSmubZJdM5nrbauINvjNiY1fCQL72knNXXgg31dlLwxZ3J 17 | 1R4ytprYrkAPmEofDI+MIugu+8+T9XnSIw5YshWT5EKT+YGP76C2FKCpB7HKScRw 18 | JMFZLaGLIGKYybzC0k4f8QIDAQABo2YwZDAdBgNVHQ4EFgQULwwfX0lG6sS3zGb/ 19 | 0gaRki8MG6swHwYDVR0jBBgwFoAUxVbJgvLbara0rOyfJEDcLupTakYwEgYDVR0T 20 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIB 21 | AEvdAabcAEPf/TymeslC/zpvclfoED9hiqx/VEaL5Hq5xQdCKUMebgqOSIXPaLTZ 22 | VuL+wjcsOdwEH79jSWPtn7zUfEX18qQfcG/WJCaKkKbnr9inbbJp4YEKvyHmV42D 23 | UKLxXwLu95NDhZN/J6xh0IrbDsu8gzjiWZKP86PUKZbH7AnLyKwFy3zAJNl4QbwY 24 | WtzHb8x3gm6+63QzkJfY3GD19VUqtDDRM4XoEjgnq5hoPEx1mvOg2AHOqlMLQuGG 25 | 5sMv+sqIf4yOPlm2EeyArFnBf7DJghxqfzxMR5dsp5nzXh6OJHawTt9F3d30MBmC 26 | 6Q1v+zozfuJ/DSpEbAS0Vg7H7WZbEEDCX5c+Qe+ot6j8p/fVjWZMNrTvn5bQo6gf 27 | vrif3KfXd7Ja1dI89jsQHw9ugRk1vPmJVAOKoV+I2lNP2gEUNmmw0A0Q01rQYrXT 28 | t5WdMwVgbU/lnF2m3+TRlicWSlORhzJ2BbVklPE1v9D0gogcc7AQNtIYKgdWHlot 29 | QFEOewr7ijkEhaTvNHdTBQif3ltLW+rgc9Ts/zrp6NVh1rXt5PNsaUks8pvKF0al 30 | ewgHt6+9otWaYb7iF8hAe2lVS8xDo3DAQ1oGBJucnhJ2pXxTza+qG3TqCKlAwFr9 31 | AGECqlNMaBDdFjX2cWZuUlYlunKlgpridZPvTp3MffhR 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /t/fixtures/crl/subca.cnf: -------------------------------------------------------------------------------- 1 | # OpenSSL intermediate CA configuration file. 2 | # Copy to `/root/ca/intermediate/openssl.cnf`. 3 | 4 | [ ca ] 5 | # `man ca` 6 | default_ca = CA_default 7 | 8 | [ CA_default ] 9 | # Directory and file locations. 10 | dir = ./subca 11 | new_certs_dir = $dir/newcerts 12 | database = $dir/index.txt 13 | serial = $dir/serial 14 | RANDFILE = $dir/.rand 15 | 16 | # The root key and root certificate. 17 | private_key = subca.key.pem 18 | certificate = subca.cert.pem 19 | 20 | # For certificate revocation lists. 21 | crlnumber = $dir/crlnumber 22 | crl = $dir/intermediate.crl.pem 23 | crl_extensions = crl_ext 24 | default_crl_days = 30 25 | 26 | # SHA-1 is deprecated, so use SHA-2 instead. 27 | default_md = sha256 28 | 29 | name_opt = ca_default 30 | cert_opt = ca_default 31 | default_days = 365 32 | preserve = no 33 | policy = policy_loose 34 | 35 | [ policy_strict ] 36 | # The root CA should only sign intermediate certificates that match. 37 | # See the POLICY FORMAT section of `man ca`. 38 | countryName = match 39 | stateOrProvinceName = match 40 | organizationName = match 41 | organizationalUnitName = optional 42 | commonName = supplied 43 | emailAddress = optional 44 | 45 | [ policy_loose ] 46 | # Allow the intermediate CA to sign a more diverse range of certificates. 47 | # See the POLICY FORMAT section of the `ca` man page. 48 | countryName = optional 49 | stateOrProvinceName = optional 50 | localityName = optional 51 | organizationName = optional 52 | organizationalUnitName = optional 53 | commonName = supplied 54 | emailAddress = optional 55 | 56 | [ req ] 57 | # Options for the `req` tool (`man req`). 58 | default_bits = 2048 59 | distinguished_name = req_distinguished_name 60 | string_mask = utf8only 61 | 62 | # SHA-1 is deprecated, so use SHA-2 instead. 63 | default_md = sha256 64 | 65 | # Extension to add when the -x509 option is used. 66 | x509_extensions = v3_ca 67 | 68 | [ req_distinguished_name ] 69 | # See . 70 | countryName = Country Name (2 letter code) 71 | stateOrProvinceName = State or Province Name 72 | localityName = Locality Name 73 | 0.organizationName = Organization Name 74 | organizationalUnitName = Organizational Unit Name 75 | commonName = Common Name 76 | emailAddress = Email Address 77 | 78 | # Optionally, specify some defaults. 79 | countryName_default = GB 80 | stateOrProvinceName_default = England 81 | localityName_default = 82 | 0.organizationName_default = Alice Ltd 83 | organizationalUnitName_default = 84 | emailAddress_default = 85 | 86 | [ v3_ca ] 87 | # Extensions for a typical CA (`man x509v3_config`). 88 | subjectKeyIdentifier = hash 89 | authorityKeyIdentifier = keyid:always,issuer 90 | basicConstraints = critical, CA:true 91 | keyUsage = critical, digitalSignature, cRLSign, keyCertSign 92 | 93 | [ usr_cert ] 94 | # Extensions for client certificates (`man x509v3_config`). 95 | basicConstraints = CA:FALSE 96 | nsCertType = client, email 97 | nsComment = "OpenSSL Generated Client Certificate" 98 | subjectKeyIdentifier = hash 99 | authorityKeyIdentifier = keyid,issuer 100 | keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment 101 | extendedKeyUsage = clientAuth, emailProtection 102 | authorityInfoAccess = OCSP;URI:http://ocspserver:2560 103 | crlDistributionPoints = @crl_info 104 | 105 | [ crl_ext ] 106 | # Extension for CRLs (`man x509v3_config`). 107 | authorityKeyIdentifier=keyid:always 108 | 109 | [ crl_info ] 110 | URI.0 = http://ocspserver:80/crl.pem 111 | -------------------------------------------------------------------------------- /t/fixtures/crl/subca.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /t/fixtures/crl/valid.cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 36 | -----END CERTIFICATE----- 37 | -------------------------------------------------------------------------------- /t/fixtures/crl/valid.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEAro5s2capnXcBZHv7EFje783FXbTQ4GoXL41ZnUO1toGArZd+ 3 | aQGExXAOUVllhVfH62XkW8ebuXar1v7pw9L8RIv13Cl05bsWYaX0LhY3C9Ll2yp/ 4 | 0BTNf/QyBvoIRnsunj3UcdU3n3/9uJWUml30RcZ5iwNHnLlvOQWIV/AsibmseAtu 5 | inJGHak1jD7TB561w/s/GhDc2e8HCuRxxt0KuHrXmi06qmJWf0yrOxWRoaiBai5m 6 | 4Xg7BA+h/zOa42gXZSBsxqwGYesysPjy6FafEuYEnzyZsM7gifr4+cnHw7SbaHAA 7 | G748tMkoJ+154T/eZvKmOLpHHZCtoxTRdkwV5QIDAQABAoIBAEqAt6zrwhFXbdy5 8 | nhsIE38+0HKCbnSaU3MUXZ9l+vT+qTFua6Hd6BFtFm9aPJ6BLO8n+iPCOpEaOZX2 9 | D0hpkQqgwjtJ5n73L0JWVrYk/TGqvjihFxR1DJEEZSXdKhMLGIap1TcQzkDhnCVg 10 | kqCgYVY2tEHFEJev/ezUk7EU7a2KQW1kOJPEGDJR7UU0Kwx3RUY0BhBstuDCWPwp 11 | cZxw3JFvfxuNThxyqLWX8IbmvTlptLSUpcDyg4BQJ+wM28w4uwQkyc9DnLfoEbO9 12 | l4aIjIx7pkZ64JSBppGt203Q7rG/7TQUR/FPU0lFDmuQ470kLn09MYJV0GCmdVAO 13 | 3O/tCrECgYEA4Khz8wi157a8LkA7gXdjv+dsdWZe5IYodH0swSt2GIHLBlWGwheO 14 | 23FiovifnNbbSZmRfTHXBuKOdWjxr3gULtO5KD2wdv9cYJnl9uL1FbrwJQI3v9xD 15 | 1ezHLuGCFjxFmYu+t6SVHYHl21MfT1W6bx+ZrcliDJPJqh368nXF98MCgYEAxuid 16 | 1ZALHOy+1TmfYFjk88LrljoYL6DlyH2pNqX+7viZVcxHfpkK26kgVtTA0YmKDzt1 17 | nG2yOOaRm+j8CUgRw8TW54N6evZM/BTPmITsN1UHrSXixwT0hIZkP92rHcEj+GrK 18 | lDrDmjJDLe2rI39nmj5YSU5wsdI8QFbmbX3aCTcCgYBowUOnvJUNoeCndF4K5X/G 19 | uQOSzpRK3N+6Sa/3tutPTB4+Kt02XcPIQVusAGB0wp7n98qmZPoOBNBGoROpLUXD 20 | /AenYvSI2FPb24cmkveTFWLq7tjOBsg+1TSfgJmnAp21ljrs6Lp7Utm6Zk0AMkpH 21 | jKWdKn0kvjjXsTkVm6Me/wKBgGqVCMX/2kSUgykkKEdrOrt3bd9gn8cdsyL8Wqii 22 | x/jrEtbLkF/Ax/WuKVr9w5hD18uTs9CvYvlkaw+dBzg9+u7o0bLaW835noTQ7fAv 23 | AZggou1fyKWV/SPqE1u5ftCBxrF9H7HPzzIXzrGUkciCo1QeJhaZxn8yRQDAz9ZJ 24 | woR/AoGAeO6Eu1wroUchYHQ7VglAJQDVyXukdfgBJWRGG3I9R+wMiHs8iF2MSvBa 25 | 941DZr6mNXOSrcR3FdO+EHP8FtMpYe6EJPSC8bk2Nl75OVptx+Wcd+VJ6DZQysYZ 26 | MgMGpHdHTZAfLDBje9yF0K7XluxaBaY6gqn+xPgqT/AOOE3xZqQ= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /t/fixtures/ec_key_encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,74AB7E7042FC695A7F267BB416AC24E1 4 | 5 | zNvboWr/ayt4McuSl9h3oirnS7DK5JU5OSGvh3Seyt9E1oVd3SUg4Mcp4BpZP8gv 6 | Ei4K6+p3CTDrQfE0mrjIph3C1LKTzQeLdGIvgTjjKVpu91aogU3K3rgcuqKN/zla 7 | +sQOAedKEtLiop4J6rIGmKvo9JZonbMsEZnZnXGbz3k= 8 | -----END EC PRIVATE KEY----- 9 | -------------------------------------------------------------------------------- /t/fixtures/no_revoked.crl: -------------------------------------------------------------------------------- 1 | -----BEGIN X509 CRL----- 2 | MIICyTCBsgIBATANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJVUzEpMCcGA1UE 3 | ChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT 4 | UkcgUm9vdCBYMRcNMjIwNTE4MDAwMDAwWhcNMjMwNDE3MjM1OTU5WqAvMC0wHwYD 5 | VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wCgYDVR0UBAMCAWYwDQYJKoZI 6 | hvcNAQELBQADggIBAC2us3ieEcU7NTFjPyXEi/5aOID7IlPBK7ugS7IJrasTyEdH 7 | fAMcuoEGHaLoyLqpIKc7U/KIfqysn6l4Mu32aWFB/Ck5qiVufHXFjXIuNo4/drlm 8 | kPUjhgX0YcMkrWdbLFbF/mi5R7fCTbCP1ihqiw2AKB2jFShTAcybJpVRY7velN/D 9 | EI8ITJsHnGNOx5XZV7HgO1SbXrba7YGMD0YA+NiXc8VaoDlZdoKh8q/gk8y5vnvL 10 | UmtsHpdF1zFwDxYdpFLCrV9z8OcPWjguX6bYMWtnN5JPHrlUQrupCIN55ur8ttoq 11 | +9mQ/3Y2OFl1qF6UtHxSDHAI5vA8dBlZxQWSWXKGFPGPssNdB7CUJlZeLWPICWU9 12 | yANMxG+5ANeXW65GfPexj2DujwDlC46Wdnlvbft+2Bc0SYR72By/1QB3tmgBB//j 13 | QuJtAIzvRluvdnoIGRHPGVse0Qk4FC2BK04q8HBRw3UbxV1MDYIFCN9hlC625Q1s 14 | VjrqzGMPAwXYXNa/9hFQkdjKycrdsGvIXZa08sqqx4hY4CpjEeUQoka0XkTUmp7Q 15 | GDSXFxe4qxQObnU+LAMQ0cEcVb0TNnTC0PCeoSV82n3jRL9QYMe6lvU4pgFMddXz 16 | jna557uivEENf58Oh0SH5jux5gSlre177jQvvsfn8FeFXsLijw0tCbfupna/ 17 | -----END X509 CRL----- 18 | 19 | -------------------------------------------------------------------------------- /t/fixtures/openssl_fips.cnf: -------------------------------------------------------------------------------- 1 | config_diagnostics = 1 2 | openssl_conf = openssl_init 3 | 4 | [openssl_init] 5 | providers = provider_sect 6 | 7 | [provider_sect] 8 | fips = fips_sect 9 | default = default_sect 10 | 11 | [default_sect] 12 | activate = 1 13 | 14 | # need fipsinstall to populate below section 15 | # [fips_sect] 16 | 17 | -------------------------------------------------------------------------------- /t/fixtures/rsa-pkcs1-priv.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAxpgb1ESW7DpRvUHd56f1WArwhETylcxu0X02mAnuRgug6pFU 3 | LobnVTuYdajuvRDdZGUYJHQuGB2Su5FiKGdDBXnuOPa/zQ6BoSz+z9Yqj8Mri0UI 4 | THXKLNqPO7/V69wbtFFus//gVozDTmv8Ws1J4lc+GYyfuVL6o8aLyGDhhrB8HoLk 5 | lYLFchkCsjt8rQ2U2fAtwWNoxlIgw707tpwR5zLe58b/aM71OOMPZlERc4VPmZTk 6 | GgYHWFJCWxnp0TQ5CIjGyigewG55Mp8XqSf5cSel/pc3rmrHVq4vrw5cLcxhJNkI 7 | UQfN9x6NvkLCBWwOLBx+HAEiLeOqIDIILObrpwIDAQABAoIBABQ0rcAvKlvmoyJq 8 | bTWAtUm78zTB/xyWrD/MSZ22hPPDgx/aoYIKX8cgRSbThVbfPGdWkdpDp9z0RVWo 9 | OSB7QSpxeXd6Q5GNhErt1Q84byQpa2jEIVAGPAfMRP6DSjSxNHBoSKcvxZeIwuZb 10 | vlVOxdGtprfawvWMJ8w6C0bb9JZLeHjdLK/O49Nxj4YrUBk+ZvkKa8EQnq/apLMz 11 | 9RMZiFQ1pvR9Ojfw4O4u0pqW80Iu8alDBxMkvzEUEhuzafrMKToX5GG65Y9/nhDl 12 | iIsENEvNY1Nk2WXPMe/VR5LVGBLtXlJ+KIj09KjuJyy5PEkwXxHobyRHEMtQ8SBs 13 | C1SE/sECgYEA+Sf1IyhyPfWg3CuGdwiYuwn9CVnZxqQWLwwk+EdIXpNDbHhfeN1Z 14 | ZC1/bttz45O4At5KtKAHLeRETuphtgwJ6ZHdNy5K6h4GV0s4ZtBHS8pu95+BAApN 15 | pGRPzZ4u4GDTkTCbHRd+A2UY1EnpGe6Owq/+Cbu67jnPJOP0pegmGzkCgYEAzAya 16 | v9pEwcDBIrKE3ida46mBAnxBT81pr8Pa5t5pON3DtjsHv3lfa01u9ga8F0GKgMif 17 | tet9dFWtFHdrC8HbrpcHwta1dVlDNzr1TSjbyl5TW9/suSbHTQ/iUmXFazbhHVu6 18 | p4jgV6DPgqxjI56YLcIqZIf2xDeVgGwbwv7d3d8CgYEAtcIpeTFrTbnfVF5IJJPX 19 | 3zJlLiomzVssd7vTSG+v4pZpbDrP4vsO2B68xOFAxHchmK4TL3tCYX8ROcSP7V8Q 20 | 6BwplbSmn+2xUIMmLRKpwCd4Fhp838ukYlVvRh+sMLFSBavArFNT8SQSHeOhMfKu 21 | oGYE25LgxiLT8yR8d39INTkCgYEAilnxgyvnesfLLE+Gr2pXwg1oH9tIHWfVxQsz 22 | HV6oUZpr3N9hfX46KHM0TTR7y/jwhCmDwMGPKpX86OefeTVUUqis5nrWRl7jqEsd 23 | j9eoTyptstm9lDyq3aFrfxrqJKvtLw7HHFk+Y6vxh1SDU99wp3YDcG6P7rMRdyXW 24 | HPzaSlkCgYBums2fZgP96/wyburnMhP/86ndLyVB2YbLwXMz+oGlm+XssAawulrM 25 | 6mxpV63T+/UmEiszCEf3ZOUr1+zkSTe/CMZk5Vev1pYEzfpQ2AnpOsvPw+WGQbWL 26 | 95dYCSGZKjXQ/UV+zDisZiDzjLRkZ7WfPJsPZ8z1P3nZ2t+8IRNO/Q== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /t/fixtures/rsa-pkcs1-pub.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PUBLIC KEY----- 2 | MIIBCgKCAQEAxpgb1ESW7DpRvUHd56f1WArwhETylcxu0X02mAnuRgug6pFULobn 3 | VTuYdajuvRDdZGUYJHQuGB2Su5FiKGdDBXnuOPa/zQ6BoSz+z9Yqj8Mri0UITHXK 4 | LNqPO7/V69wbtFFus//gVozDTmv8Ws1J4lc+GYyfuVL6o8aLyGDhhrB8HoLklYLF 5 | chkCsjt8rQ2U2fAtwWNoxlIgw707tpwR5zLe58b/aM71OOMPZlERc4VPmZTkGgYH 6 | WFJCWxnp0TQ5CIjGyigewG55Mp8XqSf5cSel/pc3rmrHVq4vrw5cLcxhJNkIUQfN 7 | 9x6NvkLCBWwOLBx+HAEiLeOqIDIILObrpwIDAQAB 8 | -----END RSA PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /t/fixtures/test.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDBzCCAe+gAwIBAgIUJ+FXF8zL+pdK8Nl68Eq0aQlZKNMwDQYJKoZIhvcNAQEL 3 | BQAwEzERMA8GA1UEAwwIdGVzdC5jb20wHhcNMjAxMjE1MTAwNjIyWhcNMzAxMjEz 4 | MTAwNjIyWjATMREwDwYDVQQDDAh0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD 5 | ggEPADCCAQoCggEBAMEQQC0nyiHOekSs6sTwLBrdiWYvDWC5OQylQZY2pWsBYtWH 6 | 3rkkt98rRNC3cxLSPwH+AAJrJCnRl4ZIxUrtNF8zPW/NexAaarKMLq8LHnVD+cf5 7 | uLzK9xZNt5s8aTQOF8TuHH2Zq/jdfJ9MnAJf1noZ4Oz5IZqOtgJ+1oCDZJc4ZlL1 8 | KO5tfDsWZOsRdow6F7wlK1xtCfcakcncL7Yh4xbZYQXnNSliGZF0/+SIqYIGhv2f 9 | EBng0yOW6FrXtrxhj/7TplAd2v5ziCsdcqqA+YFu4e6PzFybNErUgNZ8ZsokmP56 10 | uU13oKYLIsEf11EmKEX1bwvEvvu+T/V/IB38YV8CAwEAAaNTMFEwHQYDVR0OBBYE 11 | FM8D9Qnrg9JPEN5lkpDpkz44TOh8MB8GA1UdIwQYMBaAFM8D9Qnrg9JPEN5lkpDp 12 | kz44TOh8MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAI/ODar1 13 | fVkJ50rLToICvp2zZkLSsZlL13Gy4+FUUl0sctSRbXF6yPZGa3u6/HeF5AWnrFNX 14 | eZUVuJgyYa2gmz0K+HGbSrbNFb4Cpnhe7Y722SpSDEj3ybOI3EBeRT3WcwpSsGKa 15 | Kfx8NY08J440cn3oNAbZ9XrZOHhyvjkCEr9+ieg1MvMtNg5NbTpHj6Riuvuvvs3s 16 | CaOJ1dN5a59hHHvt76lb6Ah3cwJ98CRAObp1bElgL//Tl9faAHAFIpGopvq41Jnn 17 | rBd/GtvM6J/LHznZ9eOvMq+uBMyAhzpmi6Ih4SGnwN/i8StRbNvpIUIq2rO6IvCZ 18 | 61xzxPhcY6bB2KI= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /t/fixtures/test.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIDFTCCAf0CAQAwejELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx 3 | FDASBgNVBAcTC0xvcyBBbmdlbGVzMRQwEgYDVQQKEwtTU0wgU3VwcG9ydDEUMBIG 4 | A1UECxMLU1NMIFN1cHBvcnQxFDASBgNVBAMTC2V4YW1wbGUuY29tMIIBIjANBgkq 5 | hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPOIBIoblSLFv/ifj8GDCNL5NhDX2JVU 6 | QKcWC19KtWYQg1HPnaGIy+Dj9tYSBw8T8xc9hbJ1TYGbBIMKfBUzKoTt5yLdVIM/ 7 | HJm3m9ImvAbK7TYcx1U9TJEMxN6686whAUMBr4B7ql4VTXqu6TgDcdbcQ5wsPVOi 8 | FHJTTwgVwt7eVCBMFAkZn+qQz+WigM5HEp8KFrzwAK142H2ucuyfgGS4+XQSsUdw 9 | NWh9GPRZgRt3R2h5ymYkQB/cbg596alCquoizI6QCfwQx3or9Dg1f3rlwf8H5HIV 10 | H3hATGIr7GpbKka/JH2PYNGfi5KqsJssVQfu84m+5WXDB+90KHJEcwIDAQABoFYw 11 | VAYJKoZIhvcNAQkOMUcwRTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUE 12 | DDAKBggrBgEFBQcDATAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkqhkiG9w0B 13 | AQUFAAOCAQEAgBSVMeTB9pfgZCllMPBFffeduMePyDA1SzLYjSFkh660sFFiwGAV 14 | MTnnYFHH3k6ueRVal3gzxZJ6ehr+ms1/CRO8rlY+B6geMCbGCbCvcAET0n505aYH 15 | v8vlvqrdSx8Ur/9sisbynCkdk2qgc3rbnDbsAAonZIXf+blacaYTZdGUxso6qtY6 16 | 6mhI+ulqmkDk3Quc02ityvuGEbN8UuUGxc+kg0aIqMWWNKUGpTq/aRWpC7kuCUFZ 17 | fmvPwnMhzgKBPzOXwyauVxAV0Mm/1uwPu9GNVQDgewy4Rjbm5bNwIjce3W1tVMWT 18 | FR+x0BtV+D2A62fJWB2Yv9oERJbZQnvLqw== 19 | -----END CERTIFICATE REQUEST----- -------------------------------------------------------------------------------- /t/fixtures/test.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBEEAtJ8ohznpE 3 | rOrE8Cwa3YlmLw1guTkMpUGWNqVrAWLVh965JLffK0TQt3MS0j8B/gACayQp0ZeG 4 | SMVK7TRfMz1vzXsQGmqyjC6vCx51Q/nH+bi8yvcWTbebPGk0DhfE7hx9mav43Xyf 5 | TJwCX9Z6GeDs+SGajrYCftaAg2SXOGZS9SjubXw7FmTrEXaMOhe8JStcbQn3GpHJ 6 | 3C+2IeMW2WEF5zUpYhmRdP/kiKmCBob9nxAZ4NMjluha17a8YY/+06ZQHdr+c4gr 7 | HXKqgPmBbuHuj8xcmzRK1IDWfGbKJJj+erlNd6CmCyLBH9dRJihF9W8LxL77vk/1 8 | fyAd/GFfAgMBAAECggEAG+N4Ec3MoiOMf/0mkLpM9LiJz4v+d7lp50y787IDJTj3 9 | CPdukfoe4YsDjs7hPZfHaEdDwxWtDKltJQXAEjm/tfzV5B+fpkzamt4rJDgL906R 10 | d3S4XfVHyh4B5tfMLqvWfSkUToRzVijQhsZvRtyHQ+4XEsROOWBiJGwkGj5guoM3 11 | 4ItEJOXece+4pV0M1KPb3aTqGLw/Iow1IV9k+HCKrxwsBK0xpoEYfvK6N6PsmcRK 12 | iPS53D6bCS74HidgXvhPN8hdVvJ+s8rvXDdVF3Ajw/LhrdeYrRjZUtRpB43Z8uLn 13 | raMMOid4Q9EEsZNcWG2UO6BHyDibkOzQmPIv0/JIgQKBgQDo1Cmd3ialMZkn9bSX 14 | DUNxMZlTk49Abns2rKojRxApU3h3aVuViXPIs3yz0cUPzURGHOOHQwU5cFjMVsxx 15 | GffZjNq+ViR1Il0UhxBlYlcRZOou4RSi6VnN8HRjNeBNrzGxo/C+9/U00/APT/z5 16 | OBloEoWy22SqTJtQCKspQ60knwKBgQDURvpcMlJE6UBhIy3Q3/7+HUc/AsCj5dMY 17 | OafioeuKO+fRcNBaith3bUF3aRplf2jD/pQ/nLvD4+q0tvaEY06jpiVwm5PXGdUy 18 | acIcs56ch1BiczP5pkSpEpaG0ap4btW86UU3K+at0iAJqfm9aR8DSOugl+D+EC16 19 | RDRKn4TLQQKBgQDA4vPPW7m8ZYiyuDXyZgSXhDW4LakiAeWF+CnDrB3RfttwYhKD 20 | oioP/dKzzndpje6f/1LoPjfXzCFkuAwLLy5MRwr5YLg3ak6esP5+X6guOuJgEAxe 21 | ot/JYwmpH3tCIIAU4PKT4yx7pZFdvjCf7z/tHlsxP9z30RtihKv4NZ79lQKBgBOL 22 | XW2zrGNv3l+TL5q1pPKcm3yvsjDk7iSi2lRBeEBH97YO3wAXHIsSYh6ubKG/s1Oo 23 | UtnwglEs4OU2m0fhJNJob7YIfPonBLwZhKfD2eyrgLkvxi9MIbI3ZeiP0VQ5UDCO 24 | gbLstdZ3LD/3iGjqDtLsmdU1Zp+9uZIySWY9faqBAoGAa3DJYcGpBQWDlNbojcgv 25 | VUNukUrxDQOLR6AbPcYF8EdrSgtkuDQJfb94HpR55u6o+l9SiD2t9uEl/rLqrp1+ 26 | jOTte0IERqrerKp43G/AHZduw0ks4PPxglZUAQ1/HSTUTUvACoHFB9egElj3zNIX 27 | fFBB0c+kqU2aLFq342F0ONU= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /t/openssl/ctx.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.myassert = require("helper").myassert 19 | } 20 | }; 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: Can create a ctx in ngx.ctx 27 | --- http_config eval: $::HttpConfig 28 | --- config 29 | location =/t { 30 | content_by_lua_block { 31 | if not require("resty.openssl.version").OPENSSL_3X then 32 | ngx.exit(0) 33 | end 34 | local ctx = require("resty.openssl.ctx") 35 | myassert(ctx.new(true)) 36 | } 37 | } 38 | --- request 39 | GET /t 40 | --- no_error_log 41 | [error] 42 | 43 | 44 | 45 | === TEST 2: Can create a ctx in global namespace 46 | --- http_config eval: $::HttpConfig 47 | --- config 48 | location =/t { 49 | content_by_lua_block { 50 | if not require("resty.openssl.version").OPENSSL_3X then 51 | ngx.exit(0) 52 | end 53 | local ctx = require("resty.openssl.ctx") 54 | myassert(ctx.new()) 55 | } 56 | } 57 | --- request 58 | GET /t 59 | --- no_error_log 60 | [error] 61 | 62 | 63 | 64 | === TEST 3: Can free ctx in ngx.ctx 65 | --- http_config eval: $::HttpConfig 66 | --- config 67 | location =/t { 68 | content_by_lua_block { 69 | if not require("resty.openssl.version").OPENSSL_3X then 70 | ngx.exit(0) 71 | end 72 | local ctx = require("resty.openssl.ctx") 73 | myassert(ctx.new(true)) 74 | myassert(ctx.free(true)) 75 | } 76 | } 77 | --- request 78 | GET /t 79 | --- no_error_log 80 | [error] 81 | 82 | 83 | 84 | === TEST 4: Can free ctx in global namespace 85 | --- http_config eval: $::HttpConfig 86 | --- config 87 | location =/t { 88 | content_by_lua_block { 89 | if not require("resty.openssl.version").OPENSSL_3X then 90 | ngx.exit(0) 91 | end 92 | local ctx = require("resty.openssl.ctx") 93 | myassert(ctx.new()) 94 | myassert(ctx.free()) 95 | } 96 | } 97 | --- request 98 | GET /t 99 | --- no_error_log 100 | [error] 101 | -------------------------------------------------------------------------------- /t/openssl/err.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | } 19 | }; 20 | 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: Don't cry if there's no error 26 | --- http_config eval: $::HttpConfig 27 | --- config 28 | location =/t { 29 | content_by_lua_block { 30 | local format_error = require("resty.openssl.err").format_error 31 | 32 | ngx.print(format_error("fake function")) 33 | } 34 | } 35 | --- request 36 | GET /t 37 | --- response_body eval 38 | "fake function failed" 39 | --- no_error_log 40 | [error] 41 | -------------------------------------------------------------------------------- /t/openssl/hmac.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.myassert = require("helper").myassert 19 | } 20 | }; 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: Calculate hmac correctly 27 | --- http_config eval: $::HttpConfig 28 | --- config 29 | location =/t { 30 | content_by_lua_block { 31 | local hmac = myassert(require("resty.openssl.hmac").new("goose", "sha256")) 32 | 33 | myassert(hmac:update("🦢🦢🦢🦢🦢🦢")) 34 | ngx.print(ngx.encode_base64(myassert(hmac:final()))) 35 | } 36 | } 37 | --- request 38 | GET /t 39 | --- response_body eval 40 | "kwUMjYrP0BSJb8cIJvWYoiM1Kc4mQxZOTwSiTTLRhDM=" 41 | --- no_error_log 42 | [error] 43 | 44 | 45 | 46 | === TEST 2: Update accepts vardiac args 47 | --- http_config eval: $::HttpConfig 48 | --- config 49 | location =/t { 50 | content_by_lua_block { 51 | local hmac = myassert(require("resty.openssl.hmac").new("goose", "sha256")) 52 | 53 | hmac:update("🦢", "🦢🦢", "🦢🦢", "🦢") 54 | ngx.print(ngx.encode_base64(hmac:final())) 55 | } 56 | } 57 | --- request 58 | GET /t 59 | --- response_body eval 60 | "kwUMjYrP0BSJb8cIJvWYoiM1Kc4mQxZOTwSiTTLRhDM=" 61 | --- no_error_log 62 | [error] 63 | 64 | 65 | 66 | === TEST 3: Final accepts optional arg 67 | --- http_config eval: $::HttpConfig 68 | --- config 69 | location =/t { 70 | content_by_lua_block { 71 | local hmac = myassert(require("resty.openssl.hmac").new("goose", "sha256")) 72 | 73 | myassert(hmac:update("🦢", "🦢🦢", "🦢🦢")) 74 | ngx.print(ngx.encode_base64(myassert(hmac:final("🦢")))) 75 | } 76 | } 77 | --- request 78 | GET /t 79 | --- response_body eval 80 | "kwUMjYrP0BSJb8cIJvWYoiM1Kc4mQxZOTwSiTTLRhDM=" 81 | --- no_error_log 82 | [error] 83 | 84 | 85 | 86 | === TEST 4: Rejects unknown hash 87 | --- http_config eval: $::HttpConfig 88 | --- config 89 | location =/t { 90 | content_by_lua_block { 91 | local hmac, err = require("resty.openssl.hmac").new("goose", "sha257") 92 | ngx.print(err) 93 | } 94 | } 95 | --- request 96 | GET /t 97 | --- response_body_like eval 98 | "hmac.new:.+(?:invalid|unsupported).*" 99 | --- no_error_log 100 | [error] 101 | 102 | 103 | 104 | === TEST 5: Can be reused 105 | --- http_config eval: $::HttpConfig 106 | --- config 107 | location =/t { 108 | content_by_lua_block { 109 | local hmac = myassert(require("resty.openssl.hmac").new("goose", "sha256")) 110 | myassert(hmac:update("🦢🦢🦢🦢🦢🦢")) 111 | ngx.say(ngx.encode_base64(myassert(hmac:final()))) 112 | 113 | myassert(hmac:reset()) 114 | 115 | myassert(hmac:update("🦢🦢🦢🦢🦢🦢")) 116 | ngx.say(ngx.encode_base64(myassert(hmac:final()))) 117 | } 118 | } 119 | --- request 120 | GET /t 121 | --- response_body eval 122 | "kwUMjYrP0BSJb8cIJvWYoiM1Kc4mQxZOTwSiTTLRhDM= 123 | kwUMjYrP0BSJb8cIJvWYoiM1Kc4mQxZOTwSiTTLRhDM= 124 | " 125 | --- no_error_log 126 | [error] 127 | -------------------------------------------------------------------------------- /t/openssl/objects.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.encode_sorted_json = require("helper").encode_sorted_json 19 | } 20 | }; 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: Convert nid to table 27 | --- http_config eval: $::HttpConfig 28 | --- config 29 | location =/t { 30 | content_by_lua_block { 31 | local o = require("resty.openssl.objects") 32 | ngx.print(encode_sorted_json(o.nid2table(87))) 33 | } 34 | } 35 | --- request 36 | GET /t 37 | --- response_body_like eval 38 | '{"id":"2.5.29.19","ln":"X509v3 Basic Constraints","nid":87,"sn":"basicConstraints"}' 39 | --- no_error_log 40 | [error] 41 | 42 | 43 | 44 | === TEST 2: Convert txt to nid 45 | --- http_config eval: $::HttpConfig 46 | --- config 47 | location =/t { 48 | content_by_lua_block { 49 | local o = require("resty.openssl.objects") 50 | local t = { 51 | ln = "X509v3 Basic Constraints", 52 | sn = "basicConstraints", 53 | id = "2.5.29.19" 54 | } 55 | local r = {} 56 | for k, v in pairs(t) do 57 | r[k] = o.txt2nid(v) 58 | end 59 | ngx.print(encode_sorted_json(r)) 60 | } 61 | } 62 | --- request 63 | GET /t 64 | --- response_body_like eval 65 | '{"id":87,"ln":87,"sn":87}' 66 | --- no_error_log 67 | [error] 68 | 69 | 70 | 71 | === TEST 3: Convert sigid to nid 72 | --- http_config eval: $::HttpConfig 73 | --- config 74 | location =/t { 75 | content_by_lua_block { 76 | local o = require("resty.openssl.objects") 77 | ngx.print(o.find_sigid_algs(795)) -- ecdsa-with-SHA384 78 | } 79 | } 80 | --- request 81 | GET /t 82 | --- response_body eval 83 | 673 84 | --- no_error_log 85 | [error] 86 | -------------------------------------------------------------------------------- /t/openssl/param.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.encode_sorted_json = require("helper").encode_sorted_json 19 | } 20 | }; 21 | 22 | run_tests(); 23 | 24 | __DATA__ 25 | 26 | === TEST 1: Construct 27 | --- http_config eval: $::HttpConfig 28 | --- config 29 | location =/t { 30 | content_by_lua_block { 31 | ngx.say("TODO") 32 | } 33 | } 34 | --- request 35 | GET /t 36 | --- response_body 37 | TODO 38 | --- no_error_log 39 | [error] 40 | -------------------------------------------------------------------------------- /t/openssl/rand.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | } 19 | }; 20 | 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: Geneartes random bytes 26 | --- http_config eval: $::HttpConfig 27 | --- config 28 | location =/t { 29 | content_by_lua_block { 30 | local rand = require("resty.openssl.rand") 31 | local b, err = rand.bytes(233) 32 | if err then 33 | ngx.log(ngx.ERR, err) 34 | return 35 | end 36 | ngx.say(#b) 37 | local b2, err = rand.bytes(233) 38 | if err then 39 | ngx.log(ngx.ERR, err) 40 | return 41 | end 42 | ngx.say(#b2) 43 | ngx.say(b == b2) 44 | } 45 | } 46 | --- request 47 | GET /t 48 | --- response_body eval 49 | "233 50 | 233 51 | false 52 | " 53 | --- no_error_log 54 | [error] 55 | 56 | 57 | 58 | === TEST 2: Rejects invalid arguments 59 | --- http_config eval: $::HttpConfig 60 | --- config 61 | location =/t { 62 | content_by_lua_block { 63 | local rand = require("resty.openssl.rand") 64 | local b, err = rand.bytes() 65 | ngx.say(err) 66 | local b, err = rand.bytes(true) 67 | ngx.say(err) 68 | local b, err = rand.bytes({}) 69 | ngx.say(err) 70 | } 71 | } 72 | --- request 73 | GET /t 74 | --- response_body eval 75 | "rand.bytes: expect a number at #1 76 | rand.bytes: expect a number at #1 77 | rand.bytes: expect a number at #1 78 | " 79 | --- no_error_log 80 | [error] 81 | -------------------------------------------------------------------------------- /t/openssl/ssl/ssl_ctx_server.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | repeat_each(2); 8 | 9 | my $pwd = cwd(); 10 | 11 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 12 | 13 | add_block_preprocessor(sub { 14 | my ($block) = @_; 15 | 16 | my $name = $block->name; 17 | 18 | my $http_config = $block->http_config; 19 | 20 | if (defined $http_config ) { 21 | 22 | my $new_http_config = <<_EOC_; 23 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 24 | 25 | init_by_lua_block { 26 | if "1" == "$use_luacov" then 27 | require 'luacov.tick' 28 | jit.off() 29 | end 30 | _G.myassert = require("helper").myassert 31 | _G.encode_sorted_json = require("helper").encode_sorted_json 32 | } 33 | 34 | ssl_certificate $pwd/t/fixtures/test.crt; 35 | ssl_certificate_key $pwd/t/fixtures/test.key; 36 | 37 | lua_ssl_trusted_certificate $pwd/t/fixtures/test.crt; 38 | 39 | $http_config 40 | 41 | _EOC_ 42 | 43 | $block->set_value("http_config", $new_http_config); 44 | } 45 | 46 | }); 47 | 48 | 49 | our $ClientContentBy = qq{ 50 | 51 | }; 52 | 53 | no_long_string(); 54 | 55 | env_to_nginx("CI_SKIP_NGINX_C"); 56 | env_to_nginx("CI_SKIP_KONG_SSL_FUNCS"); 57 | 58 | run_tests(); 59 | 60 | __DATA__ 61 | === TEST 1: SSL (server) get peer certificate 62 | --- http_config 63 | server { 64 | listen unix:/tmp/nginx-sctx1.sock ssl; 65 | ssl_protocols TLSv1.2; 66 | server_name test.com; 67 | 68 | ssl_certificate_by_lua_block { 69 | local ssl_ctx = require "resty.openssl.ssl_ctx" 70 | local sc = assert(ssl_ctx.from_request()) 71 | assert(sc:set_alpns({"h4"})) 72 | } 73 | } 74 | --- config 75 | location /t { 76 | content_by_lua_block { 77 | local ngx_pipe = require "ngx.pipe" 78 | local opts = { 79 | merge_stderr = true, 80 | buffer_size = 256000, 81 | } 82 | local proc = ngx_pipe.spawn({'bash', '-c', "echo q | openssl s_client -unix /tmp/nginx-sctx1.sock -alpn h4 && sleep 0.1"}, opts) 83 | local data, err, partial = proc:stdout_read_all() 84 | if ngx.re.match(data, "ALPN protocol: h4") then 85 | ngx.say("ok") 86 | else 87 | ngx.say(data) 88 | end 89 | } 90 | } 91 | --- request 92 | GET /t 93 | --- response_body 94 | ok 95 | 96 | --- no_error_log 97 | [error] 98 | [emerg] 99 | 100 | -------------------------------------------------------------------------------- /t/openssl/version.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | } 19 | }; 20 | 21 | run_tests(); 22 | 23 | __DATA__ 24 | 25 | === TEST 1: Prints version text properly 26 | --- http_config eval: $::HttpConfig 27 | --- config 28 | location =/t { 29 | content_by_lua_block { 30 | local version = require("resty.openssl.version") 31 | ngx.say(version.version_text) 32 | } 33 | } 34 | --- request 35 | GET /t 36 | --- response_body_like 37 | OpenSSL \d.\d.\d.+ 38 | --- no_error_log 39 | [error] 40 | 41 | 42 | 43 | === TEST 2: Prints version text using version() 44 | --- http_config eval: $::HttpConfig 45 | --- config 46 | location =/t { 47 | content_by_lua_block { 48 | local version = require("resty.openssl.version") 49 | ngx.say(version.version(version.VERSION)) 50 | ngx.say(version.version(version.CFLAGS)) 51 | } 52 | } 53 | --- request 54 | GET /t 55 | --- response_body_like 56 | OpenSSL \d.\d.\d.+ 57 | compiler:.+ 58 | --- no_error_log 59 | [error] 60 | -------------------------------------------------------------------------------- /t/openssl/x509/csr.lua: -------------------------------------------------------------------------------- 1 | 2 | local function create_csr(domain_pkey, ...) 3 | local domains = {...} 4 | 5 | local subject = require("resty.openssl.x509.name").new() 6 | local _, err = subject:add("CN", domains[1]) 7 | if err then 8 | return nil, err 9 | end 10 | 11 | local alt, err 12 | if #{...} > 1 then 13 | alt, err = require("resty.openssl.x509.altname").new() 14 | if err then 15 | return nil, err 16 | end 17 | 18 | for _, domain in pairs(domains) do 19 | _, err = alt:add("DNS", domain) 20 | if err then 21 | return nil, err 22 | end 23 | end 24 | end 25 | 26 | local csr = require("resty.openssl.x509.csr").new() 27 | local _ 28 | _, err = csr:set_subject_name(subject) 29 | if err then 30 | return nil, err 31 | end 32 | 33 | if alt then 34 | _, err = csr:set_subject_alt_name(alt) 35 | if err then 36 | return nil, err 37 | end 38 | end 39 | 40 | _, err = csr:set_pubkey(domain_pkey) 41 | if err then 42 | return nil, err 43 | end 44 | 45 | local d = require("resty.openssl.digest").new("SHA256") 46 | _, err = csr:sign(domain_pkey, d) 47 | if err then 48 | return nil, err 49 | end 50 | 51 | return csr:tostring("DER"), nil 52 | end 53 | 54 | return { 55 | create_csr = create_csr, 56 | } 57 | -------------------------------------------------------------------------------- /t/openssl/x509/name.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.myassert = require("helper").myassert 19 | } 20 | }; 21 | 22 | 23 | run_tests(); 24 | 25 | __DATA__ 26 | 27 | === TEST 1: Duplicate the ctx 28 | --- http_config eval: $::HttpConfig 29 | --- config 30 | location =/t { 31 | content_by_lua_block { 32 | require('ffi').cdef('typedef struct X509_name_st X509_NAME; void X509_NAME_free(X509_NAME *name);') 33 | local name = myassert(require("resty.openssl.x509.name").new()) 34 | 35 | local name2 = myassert(require("resty.openssl.x509.name").dup(name.ctx)) 36 | 37 | name = nil 38 | collectgarbage("collect") 39 | -- if name2.ctx is also freed this following will segfault 40 | local _ = myassert(name2:add("CN", "example.com")) 41 | 42 | } 43 | } 44 | --- request 45 | GET /t 46 | --- response_body eval 47 | "" 48 | --- no_error_log 49 | [error] 50 | 51 | 52 | 53 | === TEST 2: Rejects invalid NID 54 | --- http_config eval: $::HttpConfig 55 | --- config 56 | location =/t { 57 | content_by_lua_block { 58 | local name = myassert(require("resty.openssl.x509.name").new()) 59 | 60 | name, err = name:add("whatever", "value") 61 | ngx.say(name == nil) 62 | ngx.say(err) 63 | } 64 | } 65 | --- request 66 | GET /t 67 | --- response_body eval 68 | "true 69 | x509.name:add: invalid NID text whatever 70 | " 71 | --- no_error_log 72 | [error] 73 | 74 | 75 | 76 | === TEST 3: Finds by text 77 | --- http_config eval: $::HttpConfig 78 | --- config 79 | location =/t { 80 | content_by_lua_block { 81 | local name = myassert(require("resty.openssl.x509.name").new()) 82 | 83 | name = myassert(name:add("CN", "example.com")) 84 | 85 | name = myassert(name:add("CN", "anotherdomain.com")) 86 | 87 | local a, b, c = name:find("CN") 88 | if a then 89 | ngx.say("found ", b, " ", a.blob) 90 | end 91 | local a, b, c = name:find("2.5.4.3") 92 | if a then 93 | ngx.say("found ", b, " ", a.blob) 94 | end 95 | local a, b, c = name:find("CM") 96 | if not a then 97 | ngx.say("not found") 98 | end 99 | local a, b, c = name:find("CN", 1) 100 | if a then 101 | ngx.say("found ", b, " ", a.blob) 102 | end 103 | } 104 | } 105 | --- request 106 | GET /t 107 | --- response_body_like eval 108 | "found 1 example.com 109 | found 1 example.com 110 | not found 111 | found 2 anotherdomain.com 112 | " 113 | --- no_error_log 114 | [error] 115 | 116 | 117 | 118 | === TEST 4: Pairs 119 | --- http_config eval: $::HttpConfig 120 | --- config 121 | location =/t { 122 | content_by_lua_block { 123 | local name = myassert(require("resty.openssl.x509.name").new()) 124 | 125 | local CNs = 3 126 | for i=1,CNs,1 do 127 | name = myassert(name:add("CN", string.format("%d.example.com", i))) 128 | end 129 | local others = { "L", "ST", "O" } 130 | for _, k in ipairs(others) do 131 | name = myassert(name:add(k, "Mars")) 132 | end 133 | ngx.say(#name) 134 | for k, v in pairs(name) do 135 | ngx.print(v.nid .. ",") 136 | end 137 | } 138 | } 139 | --- request 140 | GET /t 141 | --- response_body eval 142 | "6 143 | 13,13,13,15,16,17," 144 | --- no_error_log 145 | [error] 146 | -------------------------------------------------------------------------------- /t/openssl/x509/revoked.t: -------------------------------------------------------------------------------- 1 | # vim:set ft= ts=4 sw=4 et fdm=marker: 2 | 3 | use Test::Nginx::Socket::Lua 'no_plan'; 4 | use Cwd qw(cwd); 5 | 6 | 7 | my $pwd = cwd(); 8 | 9 | my $use_luacov = $ENV{'TEST_NGINX_USE_LUACOV'} // ''; 10 | 11 | our $HttpConfig = qq{ 12 | lua_package_path "$pwd/t/openssl/?.lua;$pwd/lib/?.lua;$pwd/lib/?/init.lua;;"; 13 | init_by_lua_block { 14 | if "1" == "$use_luacov" then 15 | require 'luacov.tick' 16 | jit.off() 17 | end 18 | _G.myassert = require("helper").myassert 19 | } 20 | }; 21 | 22 | no_long_string(); 23 | 24 | run_tests(); 25 | 26 | __DATA__ 27 | 28 | === TEST 1:revoked.new should create new revoked instance 29 | --- http_config eval: $::HttpConfig 30 | --- config 31 | location =/t { 32 | content_by_lua_block { 33 | local revoked = myassert(require("resty.openssl.x509.revoked")) 34 | local time = ngx.time() 35 | local r, err = myassert(revoked.new(1234, time, 1)) 36 | if not revoked.istype(r) then 37 | ngx.say("it should be instance of revoked") 38 | else 39 | ngx.say("ok") 40 | end 41 | } 42 | } 43 | --- request 44 | GET /t 45 | --- response_body eval 46 | "ok 47 | " 48 | --- no_error_log 49 | [error] 50 | 51 | 52 | 53 | === TEST 2:revoked.new should fail when invalid parameters are given 54 | --- http_config eval: $::HttpConfig 55 | --- config 56 | location =/t { 57 | content_by_lua_block { 58 | local revoked = myassert(require("resty.openssl.x509.revoked")) 59 | local toset = ngx.time() 60 | local r, err = revoked.new("1234", toset, 40) 61 | ngx.say(r == nil) 62 | ngx.say(err) 63 | } 64 | } 65 | --- request 66 | GET /t 67 | --- response_body eval 68 | "true 69 | x509.revoked.new: sn should be number or a bn instance 70 | " 71 | --- no_error_log 72 | [error] 73 | --------------------------------------------------------------------------------