├── .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 | php
69 | $encrypted_with_tag = sodium_crypto_aead_aes256gcm_encrypt(
70 | $to_be_encrypted,
71 | $aad,
72 | $iv,
73 | $key
74 | );
75 | ?>
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 | php
88 | $decrypted = sodium_crypto_aead_aes256gcm_decrypt(
89 | $encrypted . $tag,
90 | $aad,
91 | $iv,
92 | $key
93 | );
94 | ?>
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 | MIIGUzCCBDugAwIBAgICIAEwDQYJKoZIhvcNAQELBQAwSDELMAkGA1UECAwCQ0Ex
3 | DTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBEtvbmcxGzAZBgNVBAMMEnd3dy5zdWJj
4 | YS5rb25nLmNvbTAeFw0yMzA2MDYwNzI3MDBaFw0zMzA2MDMwNzI3MDBaMGQxCzAJ
5 | BgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBEtv
6 | bmcxDTALBgNVBAsMBEtvbmcxHTAbBgNVBAMMFHd3dy5yZXZva2VkLmtvbmcuY29t
7 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzE3ishAB+ODlQRlnbYTu
8 | vYkKBMJ+UqCCNIrAUxu6IMJWuK8hxt+KSP0RgB7LNpE/FshUuZP16dZq8A5Hah2u
9 | /r7yXEv6kmNUfAQAm3NSFT8WBgjcs3m4TTqstLhPL3sRnVECkUGEq5PHfQxR3Du/
10 | FqwYiGH6oOZXusFZzuHx0R/+GKkfkq9qomwIpZzMSIGblfS00CpWAvBYclTeJmfy
11 | nDKiDcirvG5su55lwqsqkn2Agm8y7OqQsCcaUFvnMHqxeVzk3bqXjWldfo7dviZH
12 | NW17XO5ruUJLseRZE3bCMBePQjQpY6il7K8Cq9gJ0dt3TbR9WSVNS+EUuCB3c9rt
13 | UT+qlBrNWCmMz3ZLfXDYjqiHy6jokT8K4Bo2pjoiZ7IlUZQ637xb7TOH5uIcOYsG
14 | R6Av843lt0Tv1grgaWbR/kNSOIGREO0SQakw6khpVasTNGqSoBLyFb6+Szw7EAcZ
15 | PCBh9ZOz+xXdBcGlCsmEnAwG9BSFBG4ygUdO3OyvZeSGD9BwNZFzqAi/dKJJW5Xn
16 | 1GHJQUejrrn1GiDl+NaIkprm2SXTOZ622riDb4zYmNXwkC+9pJzV14IN9XZS8MWd
17 | ydUeMraa2K5AD5hKHwyPjCLoLvvPk/V50iMOWLIVk+RCk/mBj++gthSgqQexyknE
18 | cCTBWS2hiyBimMm8wtJOH/ECAwEAAaOCASkwggElMAkGA1UdEwQCMAAwEQYJYIZI
19 | AYb4QgEBBAQDAgWgMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBD
20 | bGllbnQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFC8MH19JRurEt8xm/9IGkZIvDBur
21 | MB8GA1UdIwQYMBaAFC8MH19JRurEt8xm/9IGkZIvDBurMA4GA1UdDwEB/wQEAwIF
22 | 4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwMgYIKwYBBQUHAQEEJjAk
23 | MCIGCCsGAQUFBzABhhZodHRwOi8vb2NzcHNlcnZlcjoyNTYwMC0GA1UdHwQmMCQw
24 | IqAgoB6GHGh0dHA6Ly9vY3Nwc2VydmVyOjgwL2NybC5wZW0wDQYJKoZIhvcNAQEL
25 | BQADggIBALCjaiw5E2MSjCOWHbaJpIeTmspFLceWcFn+Vsee6IDsGfLc4X4bo2lc
26 | rTxJKjcaKHCaKBhlGYTGcAOn9aQksFxqPOnCarWhWBu7d/rtwpmS8Az6LLl6kPiq
27 | hwNR9ZXEUZubZrigbAEKOvulpCdGzS2K5r+jsyduVfUYNLgK0QQibv5gP77WLEAM
28 | UeJFXzvhYOdyd2gCegllfLdkIlt+D/4ZnMmyVYpkAPbYPTh7E1+iM0nzXrpJ68Tg
29 | nwQftjsHOGnNWg1EUt6dAGzrXlPaS5LCX5BDFGIZSIWEi0/qtySbroIwSeFiowca
30 | TwebLnONPe4cQUmga3OJg9tI6y3NRpChUPkpftmXxwQE1UT2GjecQFnSbkFsFhwv
31 | ezJjZ5iOSdpglptxPO7J8HOt32aEX0Y+qR0/QmMYYR3NdVE2aSKjaMl+8R6aIA5a
32 | akpIibDNFdOD2FU8eMCQgd+gIdne8YOpUGWIy8X+grw44DSpU7lIPmHHLQEvFiG+
33 | MrI34iCg9k9pX5D+/PnMMLMuy92VBwHVNlWe+JSVThGEPQOh7N/Bn1S4Mzv1HLUM
34 | kZrM6tTNieaoEUoArmWpwVcyNUgMO9TunNfDTOsDb144j9cK+AFdUFCKwmZyxPsR
35 | gSlWtXlcHLLMFjf5q+4jkkvZ4AVzq8NpovDKMIygjYx+BGOdqIuw
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 | MIIGUTCCBDmgAwIBAgICIAAwDQYJKoZIhvcNAQELBQAwSDELMAkGA1UECAwCQ0Ex
3 | DTALBgNVBAoMBEtvbmcxDTALBgNVBAsMBEtvbmcxGzAZBgNVBAMMEnd3dy5zdWJj
4 | YS5rb25nLmNvbTAeFw0yMzA2MDYwNzI2NTlaFw0zMzA2MDMwNzI2NTlaMGIxCzAJ
5 | BgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBEtv
6 | bmcxDTALBgNVBAsMBEtvbmcxGzAZBgNVBAMMEnd3dy52YWxpZC5rb25nLmNvbTCC
7 | AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMxN4rIQAfjg5UEZZ22E7r2J
8 | CgTCflKggjSKwFMbuiDCVrivIcbfikj9EYAeyzaRPxbIVLmT9enWavAOR2odrv6+
9 | 8lxL+pJjVHwEAJtzUhU/FgYI3LN5uE06rLS4Ty97EZ1RApFBhKuTx30MUdw7vxas
10 | GIhh+qDmV7rBWc7h8dEf/hipH5KvaqJsCKWczEiBm5X0tNAqVgLwWHJU3iZn8pwy
11 | og3Iq7xubLueZcKrKpJ9gIJvMuzqkLAnGlBb5zB6sXlc5N26l41pXX6O3b4mRzVt
12 | e1zua7lCS7HkWRN2wjAXj0I0KWOopeyvAqvYCdHbd020fVklTUvhFLggd3Pa7VE/
13 | qpQazVgpjM92S31w2I6oh8uo6JE/CuAaNqY6ImeyJVGUOt+8W+0zh+biHDmLBkeg
14 | L/ON5bdE79YK4Glm0f5DUjiBkRDtEkGpMOpIaVWrEzRqkqAS8hW+vks8OxAHGTwg
15 | YfWTs/sV3QXBpQrJhJwMBvQUhQRuMoFHTtzsr2Xkhg/QcDWRc6gIv3SiSVuV59Rh
16 | yUFHo6659Rog5fjWiJKa5tkl0zmettq4g2+M2JjV8JAvvaSc1deCDfV2UvDFncnV
17 | HjK2mtiuQA+YSh8Mj4wi6C77z5P1edIjDliyFZPkQpP5gY/voLYUoKkHscpJxHAk
18 | wVktoYsgYpjJvMLSTh/xAgMBAAGjggEpMIIBJTAJBgNVHRMEAjAAMBEGCWCGSAGG
19 | +EIBAQQEAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xp
20 | ZW50IENlcnRpZmljYXRlMB0GA1UdDgQWBBQvDB9fSUbqxLfMZv/SBpGSLwwbqzAf
21 | BgNVHSMEGDAWgBQvDB9fSUbqxLfMZv/SBpGSLwwbqzAOBgNVHQ8BAf8EBAMCBeAw
22 | HQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMDIGCCsGAQUFBwEBBCYwJDAi
23 | BggrBgEFBQcwAYYWaHR0cDovL29jc3BzZXJ2ZXI6MjU2MDAtBgNVHR8EJjAkMCKg
24 | IKAehhxodHRwOi8vb2NzcHNlcnZlcjo4MC9jcmwucGVtMA0GCSqGSIb3DQEBCwUA
25 | A4ICAQCXCJfKCUSHBKdROZKd6udawKcs0kaVN7+yrGQ928YTLlF1KaE/RIlzNdUR
26 | 66WJx/U4TT7mUGX1otpEkDk3VI2Pdq6jgU+/dVScgnW2VZ41UD4HSdzr82aVPzHP
27 | gre1bT31K/dDVLpP/ZANecixmLNFts1rgz6nKN04wFDlBYfiIG0Hr8zGU2KhW4/q
28 | d1gnvkg0fZsDquQA9wciSQ1NyCSapKdCj8/AZ5BkQAs4mh/o92yC31N/IocUTv1v
29 | KPtP6iglZ3WnIfdpuAd5KXQ3T+ZT7m7sKnX78RcJnXdj3VzePhVgYWsXR5vxpfiF
30 | D+COjdS+ANtV9hdAhT0wewFfi3r1lsDdgGlazW4zgh/zKUBR2GBfgf48e6TuQ+YV
31 | ZtUwBk02X5veqCNhbVgwDO/xlVq5EfFPh0NjUGPPa4+EKb4YIgg3OZXU4R7/f9tB
32 | BqqiiGCQUELxpLOAq2EtPsInca9+tp/MSCUQI/5RM6afs/OyMoPwNe8y1cYVK0SC
33 | tLoPvXWB19GMRyPiLqXoHZOZbxTb4op1/h3LqWuFRss7lni3booDheDRmxQgpgXJ
34 | tlqsyNRwvWjUqlNgkrwHvrbRDOhXIzUMUbHYBldSQfH3unwyk3JHB26IGYzexTrA
35 | H5c03yEn4blZKKShhJ6SzI7AUpiyKSIb0TwKJxkMsiBhr+K0Rg==
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 |
--------------------------------------------------------------------------------