summaryrefslogtreecommitdiffstats
path: root/daemon/lua/trust_anchors.test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:26:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:26:00 +0000
commit830407e88f9d40d954356c3754f2647f91d5c06a (patch)
treed6a0ece6feea91f3c656166dbaa884ef8a29740e /daemon/lua/trust_anchors.test
parentInitial commit. (diff)
downloadknot-resolver-upstream/5.6.0.tar.xz
knot-resolver-upstream/5.6.0.zip
Adding upstream version 5.6.0.upstream/5.6.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'daemon/lua/trust_anchors.test')
-rw-r--r--daemon/lua/trust_anchors.test/bootstrap.test.lua112
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_extra_attr.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_elem_extra.xml17
-rw-r--r--daemon/lua/trust_anchors.test/err_elem_missing.xml16
-rw-r--r--daemon/lua/trust_anchors.test/err_multi_ta.xml19
-rw-r--r--daemon/lua/trust_anchors.test/ok0_badtimes.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok1.xml10
-rw-r--r--daemon/lua/trust_anchors.test/ok1_expired1.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok1_notyet1.xml16
-rw-r--r--daemon/lua/trust_anchors.test/ok2.xml16
-rwxr-xr-xdaemon/lua/trust_anchors.test/regen.sh3
-rw-r--r--daemon/lua/trust_anchors.test/root.keys1
-rw-r--r--daemon/lua/trust_anchors.test/ta.test.lua85
-rw-r--r--daemon/lua/trust_anchors.test/unsupp_nonroot.xml10
-rw-r--r--daemon/lua/trust_anchors.test/unsupp_xml_v11.xml10
-rw-r--r--daemon/lua/trust_anchors.test/webserv.lua236
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca.pem24
-rw-r--r--daemon/lua/trust_anchors.test/x509/ca.tmpl4
-rwxr-xr-xdaemon/lua/trust_anchors.test/x509/gen.sh13
-rw-r--r--daemon/lua/trust_anchors.test/x509/server-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/server.pem27
-rw-r--r--daemon/lua/trust_anchors.test/x509/server.tmpl7
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca-key.pem182
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca.pem24
-rw-r--r--daemon/lua/trust_anchors.test/x509/wrongca.tmpl4
28 files changed, 1280 insertions, 0 deletions
diff --git a/daemon/lua/trust_anchors.test/bootstrap.test.lua b/daemon/lua/trust_anchors.test/bootstrap.test.lua
new file mode 100644
index 0000000..7dd248b
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/bootstrap.test.lua
@@ -0,0 +1,112 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+modules.load('ta_update')
+
+-- check prerequisites
+local has_http = pcall(require, 'kres_modules.http') and pcall(require, 'http.request')
+if not has_http then
+ -- skipping bootstrap tests because http module is not not installed
+ os.exit(77)
+end
+
+local cqueues = require("cqueues")
+local socket = require("cqueues.socket")
+
+-- unload modules which are not related to this test
+if ta_signal_query then
+ modules.unload('ta_signal_query')
+end
+if priming then
+ modules.unload('priming')
+end
+if detect_time_skew then
+ modules.unload('detect_time_skew')
+end
+
+-- Self-checks on globals
+assert(help() ~= nil)
+assert(worker.id ~= nil)
+-- Self-checks on facilities
+assert(worker.stats() ~= nil)
+assert(net.interfaces() ~= nil)
+-- Self-checks on loaded stuff
+assert(#modules.list() > 0)
+-- Self-check timers
+ev = event.recurrent(1 * sec, function () return 1 end)
+event.cancel(ev)
+ev = event.after(0, function () return 1 end)
+
+
+-- do not attempt to contact outside world using DNS, operate only on cache
+net.ipv4 = false
+net.ipv6 = false
+-- do not listen, test is driven by config code
+env.KRESD_NO_LISTEN = true
+
+-- start test webserver
+local function start_webserver()
+ -- srvout = io.popen('luajit webserv.lua')
+ -- TODO
+ os.execute('luajit webserv.lua >/dev/null 2>&1 &')
+ -- assert(srvout, 'failed to start webserver')
+end
+
+local function wait_for_webserver()
+ local starttime = os.time()
+ local connected = false
+ while not connected and os.difftime(os.time(), starttime) < 10 do
+ local con = socket.connect("localhost", 8080)
+ connected, msg = pcall(con.connect, con, 3)
+ cqueues.sleep (0.3)
+ end
+ assert(connected, string.format('unable to connect to web server: %s', msg))
+end
+
+local host = 'https://localhost:8080/'
+-- avoid interference with configured keyfile_default
+trust_anchors.remove('.')
+
+local function test_err_cert()
+ trust_anchors.bootstrap_ca = 'x509/wrongca.pem'
+ trust_anchors.bootstrap_url = host .. 'ok1.xml'
+ boom(trust_anchors.add_file, {'ok1.keys'},
+ 'fake server certificate is detected')
+end
+
+local function test_err_xml(testname, testdesc)
+ return function()
+ trust_anchors.bootstrap_ca = 'x509/ca.pem'
+ trust_anchors.bootstrap_url = host .. testname .. '.xml'
+ boom(trust_anchors.add_file, {testname .. '.keys'}, testdesc)
+ end
+end
+
+-- dumb test, right now it cannot check content of keys because
+-- it does not get written until refresh fetches DNSKEY from network
+-- (and bypassing network using policy bypasses also validation
+-- so it does not test anything)
+local function test_ok_xml(testname, testdesc)
+ return function()
+ trust_anchors.bootstrap_url = host .. testname .. '.xml'
+ trust_anchors.remove('.')
+ same(trust_anchors.add_file(testname .. '.keys'), nil, testdesc)
+ end
+end
+
+return {
+ start_webserver,
+ wait_for_webserver,
+ test_err_cert,
+ test_err_xml('err_attr_extra_attr', 'bogus TA XML with an extra attribute'),
+ test_err_xml('err_attr_validfrom_invalid', 'bogus TA XML with invalid validFrom value'),
+ test_err_xml('err_attr_validfrom_missing', 'bogus TA XML without mandatory validFrom attribute'),
+ test_err_xml('err_elem_extra', 'bogus TA XML with an extra element'),
+ test_err_xml('err_elem_missing', 'bogus TA XML without mandatory element'),
+ test_err_xml('err_multi_ta', 'bogus TA XML with multiple TAs'),
+ test_err_xml('unsupp_nonroot', 'unsupported TA XML for non-root zone'),
+ test_err_xml('unsupp_xml_v11', 'unsupported TA XML with XML v1.1'),
+ test_err_xml('ok0_badtimes', 'TA XML with no valid keys'),
+ test_ok_xml('ok1_expired1', 'TA XML with 1 valid and 1 expired key'),
+ test_ok_xml('ok1_notyet1', 'TA XML with 1 valid and 1 not yet valid key'),
+ test_ok_xml('ok1', 'TA XML with 1 valid key'),
+ test_ok_xml('ok2', 'TA XML with 2 valid keys'),
+}
diff --git a/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml b/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml
new file mode 100644
index 0000000..2a87957
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_extra_attr.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="FC4A93EC-9F4E-4597-A766-AD6723E4A56E" source="https://localhost/err_attr_extra_attr.xml">
+<Zone>.</Zone>
+<KeyDigest unknownattr="test" id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml b/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml
new file mode 100644
index 0000000..5a4c68c
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_validfrom_invalid.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="ABD668AB-52DF-4A59-80E3-16CE6341BC55" source="https://localhost/err_attr_validfrom_invalid.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-32T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml b/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml
new file mode 100644
index 0000000..1261b09
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_attr_validfrom_missing.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="3513058C-4041-40CC-AF0A-D3CCD70F962B" source="https://localhost/err_attr_validfrom_missing.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_elem_extra.xml b/daemon/lua/trust_anchors.test/err_elem_extra.xml
new file mode 100644
index 0000000..150a3b1
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_elem_extra.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="B1854D58-1867-4FA7-872F-0099D394114D" source="https://localhost/err_elem_extra.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+<UnknownElement>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</UnknownElement>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_elem_missing.xml b/daemon/lua/trust_anchors.test/err_elem_missing.xml
new file mode 100644
index 0000000..899e1d0
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_elem_missing.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="BB074095-3A42-4B13-9CC1-CFFF644D4D54" source="https://localhost/err_elem_missing.xml">
+<Zone>.</Zone>
+<KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00" validUntil="2019-01-11T00:00:00+00:00">
+<KeyTag>19036</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5</Digest>
+</KeyDigest>
+<KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
+<KeyTag>20326</KeyTag>
+<Algorithm>8</Algorithm>
+<!-- this element is missing: DigestType>2</DigestType-->
+<Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/err_multi_ta.xml b/daemon/lua/trust_anchors.test/err_multi_ta.xml
new file mode 100644
index 0000000..20cd73f
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/err_multi_ta.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="9DCE46E1-FC78-48E1-81B5-94E328790BB5" source="https://localhost/err_multi_ta.xml">
+<Zone>.</Zone>
+<KeyDigest id="1" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
+<TrustAnchor id="9DCE46E1-FC78-48E1-81B5-94E328790BB5" source="https://localhost/err_multi_ta.xml">
+<Zone>test.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok0_badtimes.xml b/daemon/lua/trust_anchors.test/ok0_badtimes.xml
new file mode 100644
index 0000000..4535a41
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok0_badtimes.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="EDEDAA08-D2A0-421E-81DC-AF11F5A0CDCD" source="https://localhost/ok0_badtimes.xml">
+<Zone>.</Zone>
+<KeyDigest id="E" validFrom="2000-01-01T00:00:00+00:00" validUntil="2000-01-01T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE</Digest>
+</KeyDigest>
+<KeyDigest id="F" validFrom="2001-01-01T00:00:00+00:00" validUntil="2001-01-01T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1.xml b/daemon/lua/trust_anchors.test/ok1.xml
new file mode 100644
index 0000000..117495c
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="82E6CB77-12DF-4E61-BF49-367FB95A8BAA" source="https://localhost/ok1.xml">
+<Zone>.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1_expired1.xml b/daemon/lua/trust_anchors.test/ok1_expired1.xml
new file mode 100644
index 0000000..f1269da
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1_expired1.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="68463155-A857-4C7E-BCA6-2F6CC2EAC1BE" source="https://localhost/ok1_expired1.xml">
+<Zone>.</Zone>
+<KeyDigest id="F" validFrom="1990-01-01T00:00:00+00:00" validUntil="2000-01-01T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+<KeyDigest id="1" validFrom="2000-01-01T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok1_notyet1.xml b/daemon/lua/trust_anchors.test/ok1_notyet1.xml
new file mode 100644
index 0000000..7b5881b
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok1_notyet1.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="507B39D5-049E-467C-9E9A-F5BE597C9DDA" source="https://localhost/ok1_notyet1.xml">
+<Zone>.</Zone>
+<KeyDigest id="1" validFrom="2010-07-15T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+<KeyDigest id="2" validFrom="2050-12-31T23:59:59+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/ok2.xml b/daemon/lua/trust_anchors.test/ok2.xml
new file mode 100644
index 0000000..149f6b5
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ok2.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="1DECEB91-0591-44A1-95CF-1788337514B8" source="https://localhost/ok2.xml">
+<Zone>.</Zone>
+<KeyDigest id="K1" validFrom="2010-07-15T00:00:00+00:00">
+<KeyTag>1</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+<KeyDigest id="K2" validFrom="2011-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>2222222222222222222222222222222222222222222222222222222222222222</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/regen.sh b/daemon/lua/trust_anchors.test/regen.sh
new file mode 100755
index 0000000..9e7dac1
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/regen.sh
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+for F in *.xml; do sed -i "s/TrustAnchor id=\"[^\"]*\"/TrustAnchor id=\"$(uuidgen | tr '[[:lower:]]' '[[:upper:]]')\"/" $F; done
+for F in *.xml; do sed -i "s#source=\"[^\"]*\"#source=\"https://localhost/$F\"#" $F; done
diff --git a/daemon/lua/trust_anchors.test/root.keys b/daemon/lua/trust_anchors.test/root.keys
new file mode 100644
index 0000000..e292b5a
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/root.keys
@@ -0,0 +1 @@
+. IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
diff --git a/daemon/lua/trust_anchors.test/ta.test.lua b/daemon/lua/trust_anchors.test/ta.test.lua
new file mode 100644
index 0000000..b977bc9
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/ta.test.lua
@@ -0,0 +1,85 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+
+trust_anchors.remove('.')
+
+local ffi = require('ffi')
+
+-- count warning messages
+warn_msg = {}
+overriding_msg="warning: overriding previously set trust anchors for ."
+warn_msg[overriding_msg] = 0
+function log_warn(grp, fmt, ...) --luacheck: no unused args
+ msg = string.format(fmt, ...)
+ if warn_msg[msg] ~= nil then
+ warn_msg[msg] = warn_msg[msg] + 1
+ end
+end
+
+-- Test that adding a revoked DNSKEY is refused.
+local function test_revoked_key()
+ local ta_c = kres.context().trust_anchors
+ same(ffi.C.kr_ta_del(ta_c, '\0'), 0, 'remove root TAs if any')
+ -- same() doesn't consider nil and typed NULL pointer equal, so we work around:
+ same(ffi.C.kr_ta_get(ta_c, '\0') == nil, true, 'no TA for root is used')
+ local key_crypto = 'AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFV'
+ .. 'QUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37'
+ .. 'NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAz'
+ .. 'vN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7O'
+ .. 'yQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0='
+ boom(trust_anchors.add, { '. 3600 DNSKEY 385 3 8 ' .. key_crypto }, 'refuse revoked key')
+ same(ffi.C.kr_ta_get(ta_c, '\0') == nil, true, 'no TA for root is used')
+ -- Test that we don't have another problem in the key
+ trust_anchors.add('. 3600 DNSKEY 257 3 8 ' .. key_crypto)
+ local root_ta = ffi.C.kr_ta_get(ta_c, '\0')
+ same(root_ta == nil, false, 'we got non-NULL TA RRset')
+ same(root_ta.rrs.count, 1, 'the root TA set contains one RR')
+end
+
+local function test_remove()
+ -- uses root key from the previous test
+ assert(trust_anchors.keysets['\0'], 'root key must be there from previous test')
+ local ta_c = kres.context().trust_anchors
+ local root_ta = ffi.C.kr_ta_get(ta_c, '\0')
+ assert(root_ta ~= nil, 'we got non-NULL TA RRset')
+ assert(root_ta.rrs.count, 1, 'we have a root TA set to be deleted')
+
+ trust_anchors.remove('.')
+
+ same(trust_anchors.keysets['\0'], nil, 'Lua interface does not have the removed key')
+ root_ta = ffi.C.kr_ta_get(ta_c, '\0')
+ same(root_ta == nil, true, 'C interface does not have the removed key')
+end
+
+local function test_add_file()
+ boom(trust_anchors.add_file, {'nonwriteable/root.keys', false},
+ "Managed trust anchor in non-writeable directory")
+
+ boom(trust_anchors.add_file, {'nonexistent.keys', true},
+ "Nonexistent unmanaged trust anchor file")
+
+ is(warn_msg[overriding_msg], 0, "No override warning messages at start of test")
+ trust_anchors.add_file('root.keys', true)
+ trust_anchors.add_file('root.keys', true)
+ is(warn_msg[overriding_msg], 1, "Warning message when override trust anchors")
+
+ is(trust_anchors.keysets['\0'][1].key_tag, 20326,
+ "Loaded KeyTag from root.keys")
+end
+
+local function test_nta()
+ assert(trust_anchors.keysets['\0'], 'root key must be there from previous tests')
+
+ trust_anchors.set_insecure({'example.com'})
+ is(trust_anchors.insecure[1], 'example.com', 'Add example.com to NTA list')
+ boom(trust_anchors.set_insecure, {{'.'}}, 'Got error when adding TA . to NTA list')
+ is(#trust_anchors.insecure, 1, 'Check one item in NTA list')
+ is(trust_anchors.insecure[1], 'example.com', 'Check previous NTA list')
+end
+
+return {
+ test_revoked_key,
+ test_remove,
+ test_add_file,
+ test_nta,
+}
+
diff --git a/daemon/lua/trust_anchors.test/unsupp_nonroot.xml b/daemon/lua/trust_anchors.test/unsupp_nonroot.xml
new file mode 100644
index 0000000..51b3c0a
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/unsupp_nonroot.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TrustAnchor id="8449BFB8-FD6C-4082-B0FE-1A3E3399203B" source="https://localhost/unsupp_nonroot.xml">
+<Zone>test.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml b/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml
new file mode 100644
index 0000000..87a4b57
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/unsupp_xml_v11.xml
@@ -0,0 +1,10 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<TrustAnchor id="3612AE1C-E8F3-4FD8-B8CD-96C7FDACC7A5" source="https://localhost/unsupp_xml_v11.xml">
+<Zone>.</Zone>
+<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
+<KeyTag>2</KeyTag>
+<Algorithm>8</Algorithm>
+<DigestType>2</DigestType>
+<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
+</KeyDigest>
+</TrustAnchor>
diff --git a/daemon/lua/trust_anchors.test/webserv.lua b/daemon/lua/trust_anchors.test/webserv.lua
new file mode 100644
index 0000000..c108bba
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/webserv.lua
@@ -0,0 +1,236 @@
+-- SPDX-License-Identifier: GPL-3.0-or-later
+
+-- This is a module that does the heavy lifting to provide an HTTP/2 enabled
+-- server that supports TLS by default and provides endpoint for other modules
+-- in order to enable them to export restful APIs and websocket streams.
+-- One example is statistics module that can stream live metrics on the website,
+-- or publish metrics on request for Prometheus scraper.
+local http_server = require('http.server')
+local http_headers = require('http.headers')
+local http_websocket = require('http.websocket')
+local http_util = require "http.util"
+local x509, pkey = require('openssl.x509'), require('openssl.pkey')
+
+-- Module declaration
+local M = {}
+
+-- Export HTTP service endpoints
+M.endpoints = {
+ ['/'] = {'text/html', 'test'},
+}
+
+-- Serve known requests, for methods other than GET
+-- the endpoint must be a closure and not a preloaded string
+local function serve(endpoints, h, stream)
+ local hsend = http_headers.new()
+ local path = h:get(':path')
+ local entry = endpoints[path]
+ if not entry then -- Accept top-level path match
+ entry = endpoints[path:match '^/[^/?]*']
+ end
+ -- Unpack MIME and data
+ local data, mime, ttl, err
+ if entry then
+ mime = entry[1]
+ data = entry[2]
+ ttl = entry[4]
+ end
+ -- Get string data out of service endpoint
+ if type(data) == 'function' then
+ local set_mime, set_ttl
+ data, err, set_mime, set_ttl = data(h, stream)
+ -- Override default endpoint mime/TTL
+ if set_mime then mime = set_mime end
+ if set_ttl then ttl = set_ttl end
+ -- Handler doesn't provide any data
+ if data == false then return end
+ if type(data) == 'number' then return tostring(data), err end
+ -- Methods other than GET require handler to be closure
+ elseif h:get(':method') ~= 'GET' then
+ return '501', ''
+ end
+ if not mime or type(data) ~= 'string' then
+ return '404', ''
+ else
+ -- Serve content type appropriately
+ hsend:append(':status', '200')
+ hsend:append('content-type', mime)
+ hsend:append('content-length', tostring(#data))
+ if ttl then
+ hsend:append('cache-control', string.format('max-age=%d', ttl))
+ end
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(data, true))
+ end
+end
+
+-- Web server service closure
+local function route(endpoints)
+ return function (_, stream)
+ -- HTTP/2: We're only permitted to send in open/half-closed (remote)
+ local connection = stream.connection
+ if connection.version >= 2 then
+ if stream.state ~= 'open' and stream.state ~= 'half closed (remote)' then
+ return
+ end
+ end
+ -- Start reading headers
+ local h = assert(stream:get_headers())
+ local m = h:get(':method')
+ local path = h:get(':path')
+ -- Upgrade connection to WebSocket
+ local ws = http_websocket.new_from_stream(stream, h)
+ if ws then
+ assert(ws:accept { protocols = {'json'} })
+ -- Continue streaming results to client
+ local ep = endpoints[path]
+ local cb = ep[3]
+ if cb then
+ cb(h, ws)
+ end
+ ws:close()
+ return
+ else
+ local ok, err, reason = http_util.yieldable_pcall(serve, endpoints, h, stream)
+ if not ok or err then
+ print(string.format('%s err %s %s: %s (%s)', os.date(), m, path, err or '500', reason))
+ -- Method is not supported
+ local hsend = http_headers.new()
+ hsend:append(':status', err or '500')
+ if reason then
+ assert(stream:write_headers(hsend, false))
+ assert(stream:write_chunk(reason, true))
+ else
+ assert(stream:write_headers(hsend, true))
+ end
+ else
+ print(string.format('%s ok %s %s', os.date(), m, path))
+ end
+ end
+ end
+end
+
+-- @function Prefer HTTP/2 or HTTP/1.1
+local function alpnselect(_, protos)
+ for _, proto in ipairs(protos) do
+ if proto == 'h2' or proto == 'http/1.1' then
+ return proto
+ end
+ end
+ return nil
+end
+
+-- @function Create TLS context
+local function tlscontext(crt, key)
+ local http_tls = require('http.tls')
+ local ctx = http_tls.new_server_context()
+ if ctx.setAlpnSelect then
+ ctx:setAlpnSelect(alpnselect)
+ end
+ assert(ctx:setPrivateKey(key))
+ assert(ctx:setCertificate(crt))
+ return ctx
+end
+
+-- @function Listen on given HTTP(s) host
+function M.add_interface(conf)
+ local crt, key
+ if conf.tls ~= false then
+ assert(conf.cert, 'cert missing')
+ assert(conf.key, 'private key missing')
+ -- Check if a cert file was specified
+ -- Read x509 certificate
+ local f = io.open(conf.cert, 'r')
+ if f then
+ crt = assert(x509.new(f:read('*all')))
+ f:close()
+ -- Continue reading key file
+ if crt then
+ f = io.open(conf.key, 'r')
+ key = assert(pkey.new(f:read('*all')))
+ f:close()
+ end
+ end
+ -- Check loaded certificate
+ assert(crt and key,
+ string.format('failed to load certificate "%s"', conf.cert))
+ end
+ -- Compose server handler
+ local routes = route(conf.endpoints or M.endpoints)
+ -- Check if UNIX socket path is used
+ local addr_str
+ if not conf.path then
+ conf.host = conf.host or 'localhost'
+ conf.port = conf.port or 8453
+ addr_str = string.format('%s@%d', conf.host, conf.port)
+ else
+ if conf.host or conf.port then
+ error('either "path", or "host" and "port" must be provided')
+ end
+ addr_str = conf.path
+ end
+ -- Create TLS context and start listening
+ local s, err = http_server.listen {
+ -- cq = worker.bg_worker.cq,
+ host = conf.host,
+ port = conf.port,
+ path = conf.path,
+ v6only = conf.v6only,
+ unlink = conf.unlink,
+ reuseaddr = conf.reuseaddr,
+ reuseport = conf.reuseport,
+ client_timeout = conf.client_timeout or 5,
+ ctx = crt and tlscontext(crt, key),
+ tls = conf.tls,
+ onstream = routes,
+ -- Log errors, but do not throw
+ onerror = function(myserver, context, op, err, errno) -- luacheck: ignore 212
+ local msg = '[http] ' .. op .. ' on ' .. tostring(context) .. ' failed'
+ if err then
+ msg = msg .. ': ' .. tostring(err)
+ end
+ print(msg)
+ end,
+ }
+ -- Manually call :listen() so that we are bound before calling :localname()
+ if s then
+ err = select(2, s:listen())
+ end
+ assert(not err, string.format('failed to listen on %s: %s', addr_str, err))
+ return s
+end
+
+-- init
+local files = {
+ 'ok0_badtimes.xml',
+ 'ok1.xml',
+ 'ok1_expired1.xml',
+ 'ok1_notyet1.xml',
+ 'ok2.xml',
+ 'err_attr_validfrom_missing.xml',
+ 'err_attr_validfrom_invalid.xml',
+ 'err_attr_extra_attr.xml',
+ 'err_elem_missing.xml',
+ 'err_elem_extra.xml',
+ 'err_multi_ta.xml',
+ 'unsupp_nonroot.xml',
+ 'unsupp_xml_v11.xml'
+}
+
+-- Export static pages specified at command line
+for _, name in ipairs(files) do
+ local fd = io.open(name)
+ assert(fd, string.format('unable to open file "%s"', name))
+ M.endpoints['/' .. name] = { 'text/xml', fd:read('*a') }
+ fd:close()
+end
+
+local server = M.add_interface({
+ host = 'localhost',
+ port = 8080,
+ tls = true,
+ cert = 'x509/server.pem',
+ key = 'x509/server-key.pem'
+ })
+
+server:loop()
diff --git a/daemon/lua/trust_anchors.test/x509/ca-key.pem b/daemon/lua/trust_anchors.test/x509/ca-key.pem
new file mode 100644
index 0000000..2e95b23
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:9e:ee:f2:d8:41:ae:2c:93:8a:01:1f:88:5b:d6:85
+ 29:2f:91:9d:37:fc:35:88:7f:53:71:87:fc:17:71:e7
+ 15:57:06:2d:54:fb:19:98:80:82:ec:1a:99:2d:57:cb
+ 5f:dd:28:26:d8:95:fb:65:b2:be:e1:11:86:69:14:7e
+ 32:5c:c0:02:0b:5d:11:78:69:50:20:25:3e:15:fb:8a
+ 46:d1:83:f9:3b:84:46:9c:69:21:44:d5:09:1d:7a:04
+ cc:f3:6a:ea:4c:1b:da:7c:40:dd:1c:6f:f6:85:b4:ea
+ 75:98:34:79:11:fb:cf:d3:18:70:64:25:33:8a:31:b6
+ 93:67:d4:32:67:61:1c:d0:7b:85:61:54:c6:fb:51:b6
+ 87:1d:d4:b8:58:40:a9:c5:32:ce:e0:b9:90:37:0d:58
+ e4:33:70:c5:c5:91:f2:18:f5:e0:08:ad:17:8b:cf:72
+ f1:26:6c:9c:88:d2:9e:06:4c:02:5d:4e:7c:93:af:8d
+ 72:93:75:1d:60:0c:f7:34:09:a8:e6:f2:80:4a:14:81
+ 24:40:4b:45:19:85:2e:ad:8e:97:4c:ff:ec:d0:9f:e6
+ a0:b7:c0:a9:a0:ad:d2:02:2d:13:55:f3:df:f8:f9:f1
+ f3:3e:35:e9:08:2b:db:11:93:57:13:55:c6:ba:c6:d7
+ ff:7d:e1:fa:8c:47:5d:da:bf:31:56:80:aa:34:97:43
+ bb:9e:ff:d3:e6:13:a9:c2:99:49:c2:1e:da:f2:c7:d2
+ d6:f7:5f:70:36:91:2f:ea:36:e9:88:44:08:a3:1a:0a
+ c0:e0:4b:48:82:9a:c9:72:29:9c:09:24:63:b3:c2:9f
+ 2a:f6:e8:3a:c4:46:03:8d:70:ae:14:bb:3a:d6:c6:62
+ 93:24:7f:bc:0a:c8:a2:20:53:3c:9f:5c:15:45:05:3d
+ 1b:38:17:d4:fe:6b:6a:c2:16:f3:14:73:c2:c3:c7:36
+ e3:f1:f8:e5:28:84:4e:37:d4:68:e8:82:70:20:53:fc
+ 01:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 44:4a:68:0e:84:2a:52:fd:12:4f:69:3d:2e:38:fe:fe
+ b3:71:de:1c:30:42:d0:63:e5:76:e2:f7:6f:1b:82:2f
+ a9:34:fe:45:85:9f:79:e7:be:59:b5:14:1c:67:9c:fb
+ 94:0b:ac:a5:63:cc:a1:e6:2c:1e:89:69:37:bd:96:7c
+ 0d:5e:73:82:6e:7b:13:42:2d:2b:a2:d5:0a:9d:0a:cd
+ 63:39:51:de:40:f8:16:3d:16:0e:7d:7b:6d:2f:00:e1
+ 0f:b6:e0:f5:d3:02:0e:61:d0:a0:67:7b:85:f8:36:c6
+ 50:a0:3b:65:7e:cd:cd:e6:b2:64:55:97:cf:c9:8c:a9
+ c9:f3:63:b5:08:05:59:8f:b9:c0:18:ad:67:4f:b5:1e
+ 59:b3:0d:82:de:46:14:75:c0:6e:cf:4d:28:5a:93:d7
+ 7a:42:fa:b7:e9:fe:1c:bb:89:88:30:d7:ed:3b:36:28
+ 68:5a:42:e8:87:97:5f:1d:49:e6:cd:d2:b9:a2:b5:23
+ d8:df:5d:cf:c6:98:9a:e0:99:7a:33:52:75:22:ce:ca
+ 85:eb:d9:92:6a:d5:49:c0:cb:df:b1:a2:98:b5:6c:37
+ 85:c2:e1:6a:13:48:22:72:02:a7:e2:e0:f3:f3:0c:ed
+ 42:f6:83:ba:71:f0:ef:8f:ce:6a:59:30:be:9d:5f:23
+ 06:c3:0e:49:5c:8f:6a:8d:c2:c3:c5:07:45:55:78:f0
+ bd:29:01:cb:ac:ec:b1:40:7d:78:cc:4d:cb:f9:60:a4
+ a2:f5:aa:21:0b:3e:da:1b:d9:f0:99:19:44:57:21:09
+ ba:0f:f9:05:8e:ee:59:4f:59:08:b1:67:51:02:80:4e
+ 34:c7:5d:25:79:8c:84:f7:be:15:02:28:9c:f9:b9:ca
+ fc:6a:ed:d0:5f:df:be:ce:c4:96:63:23:2e:db:e1:85
+ 1e:45:16:2c:24:b0:5e:7a:62:bf:36:00:8b:c8:90:61
+ c2:68:4b:95:b0:ce:41:77:a3:a0:5d:09:72:01:a0:01
+
+
+prime1:
+ 00:ca:fe:eb:14:07:13:a9:ef:b6:d5:6c:52:02:39:b6
+ 6e:55:b6:dd:70:fc:c6:04:7c:07:81:9b:98:a4:da:db
+ f1:66:b8:33:91:fd:00:15:6e:72:0d:ab:0b:6f:be:34
+ c8:d9:82:58:7e:09:7f:e4:6f:c0:70:99:53:68:c7:53
+ d2:8f:97:22:f5:e8:e4:be:5f:e1:29:0f:27:a7:66:74
+ b2:cc:96:a1:d2:ca:2a:40:4b:70:cc:7a:16:4f:c9:4f
+ 49:16:11:d5:f8:da:f6:92:06:1c:45:c3:f8:17:c4:1d
+ 65:9a:2a:3f:33:be:33:f8:84:03:26:49:d8:52:25:f8
+ 19:ce:31:00:c0:b6:55:71:74:03:53:e8:0c:ef:85:64
+ 54:d4:8f:68:08:87:da:cb:9b:55:6a:2e:2b:c2:95:36
+ c4:dd:09:62:c0:6f:9e:e9:cc:ea:96:4e:e6:2d:6c:72
+ c1:54:92:11:29:91:af:4d:cd:08:7c:f8:6f:28:9d:ca
+ c5:
+
+prime2:
+ 00:c8:6e:b7:af:c3:c6:b9:df:49:ad:ea:b8:62:b7:43
+ e6:04:d9:5a:df:c3:f9:a3:0d:b5:e6:2d:9d:f7:c4:ff
+ 38:c0:cb:03:9c:c1:d1:6f:b4:fb:cf:81:c4:9e:94:2a
+ d5:e2:a1:77:a8:7b:8f:d1:34:7a:c2:f5:38:ec:0d:35
+ a0:5e:3c:af:e9:2d:f4:f9:32:ae:da:c1:1e:62:74:e5
+ ab:3d:3b:3d:d0:88:fc:53:59:0f:21:30:ed:24:ac:a7
+ 5a:a5:b7:f4:cc:5a:96:ad:79:a3:41:74:56:ad:39:14
+ 0a:27:a4:10:18:19:33:f2:1a:aa:b4:36:9d:fa:3f:fc
+ 71:42:1e:a0:96:8e:0f:de:46:87:ba:6c:38:17:d0:7e
+ c8:4a:cb:4a:29:1c:44:b9:88:29:c7:6f:b7:4f:3f:00
+ cd:0c:6b:0f:77:a1:5a:f1:80:21:91:b3:68:ca:0d:b5
+ c9:6d:04:f4:98:94:9f:09:f9:a8:58:ea:34:9c:d8:f0
+ 0d:
+
+coefficient:
+ 00:bf:7b:93:68:64:ea:5e:b5:f4:b6:8c:91:49:aa:2b
+ b0:a5:74:40:73:45:23:b6:74:ae:7a:55:ae:9d:8a:bb
+ 3b:6d:3a:7d:c4:7a:c0:82:7f:0e:ef:57:1c:86:e2:56
+ 30:5b:0c:d9:d1:52:cf:df:10:4f:c8:4a:75:b1:b8:b1
+ 59:9b:01:02:a2:4d:29:aa:63:e5:11:0a:17:ae:1e:79
+ ed:5d:10:fc:f0:8a:8d:f6:77:f8:78:17:1e:07:ee:d1
+ de:59:ed:d7:fb:94:bf:c9:7c:f7:f3:a0:8d:66:d3:94
+ 9a:7f:d1:7a:89:87:71:17:96:90:4e:be:7b:54:5e:51
+ 03:c6:35:af:5f:ea:5d:cc:31:ab:56:4b:75:6a:14:b6
+ c0:1a:bf:fb:e9:54:ba:ad:c3:52:e9:85:03:db:b2:e8
+ 0b:18:60:37:19:f9:07:87:e7:b2:d8:3a:0d:c9:d5:f0
+ f0:73:60:fc:9e:e0:9e:b1:ea:52:71:c7:fd:27:0a:22
+ 42:
+
+exp1:
+ 04:a5:69:04:00:55:76:e2:41:b1:08:d5:a7:af:62:79
+ 8c:04:af:74:d2:94:45:ae:01:0d:fa:5d:b8:08:3a:58
+ 80:1d:5f:30:cc:35:a0:47:f2:dc:55:39:e1:c8:dc:b4
+ 6c:26:0b:98:76:e7:32:77:4c:54:47:6e:1d:4b:d2:a3
+ 53:1e:06:72:d2:6d:c9:dd:af:ed:9c:a7:2f:b1:ac:a2
+ 1b:04:a7:97:87:81:08:0f:b1:f9:3c:22:1e:99:60:f3
+ 2f:4a:21:37:9c:eb:5f:d4:3b:f9:6c:ce:d4:dc:6c:3f
+ d3:13:7c:76:d6:b7:a1:cc:83:b5:f0:a2:be:de:97:9b
+ 1f:99:07:87:61:a4:fa:ff:c8:c3:b6:df:f4:eb:7c:ac
+ 64:61:13:e4:7e:17:87:e9:7a:3e:ff:e7:88:80:99:cc
+ 4f:b2:d3:4b:cc:42:3a:df:b1:ce:d6:e7:75:ca:b1:a5
+ b3:25:d4:b6:ba:da:e4:50:f9:0c:c3:32:e8:1f:14:71
+
+
+exp2:
+ 00:9d:9d:bb:a3:63:b0:96:20:8a:5f:52:f2:b6:e6:69
+ 65:ac:30:84:ee:ec:bd:16:45:44:e3:02:c2:73:c2:9d
+ f5:b2:5e:b3:b3:85:13:3e:e6:33:13:66:78:09:40:79
+ 43:03:5a:78:af:ac:a3:57:20:0e:dd:db:5b:6c:fd:a2
+ 4b:3f:70:37:e1:85:fb:5c:30:48:22:cc:b5:29:35:c6
+ 1a:58:27:8b:1f:bf:69:b5:dd:96:31:42:b9:6a:1a:bf
+ ec:5f:df:7e:89:69:3f:8e:a1:d6:09:36:04:a7:69:f8
+ 61:57:f5:03:96:ff:d2:c2:b3:c7:c3:ba:23:97:54:d4
+ 1e:f8:a0:ff:26:06:07:62:83:52:5e:fe:95:49:dc:f2
+ a6:6d:72:da:19:e4:1a:03:50:99:92:35:3f:10:f9:79
+ 96:c6:0a:36:fa:9b:8f:d9:d4:2a:11:da:e5:2f:e7:82
+ 2a:29:2a:39:72:f7:84:ed:a2:3f:89:d4:7b:95:50:5f
+ cd:
+
+
+Public Key PIN:
+ pin-sha256:u7TPTyh/innOijbJFG3Y4pWghApErLvhCQUZNXBlVFU=
+Public Key ID:
+ sha256:bbb4cf4f287f8a79ce8a36c9146dd8e295a0840a44acbbe10905193570655455
+ sha1:92b7d0c4d107e2a73f827b87866aef9ff4379cc8
+
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/ca.pem b/daemon/lua/trust_anchors.test/x509/ca.pem
new file mode 100644
index 0000000..e3c3ca2
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEGTCCAoGgAwIBAgIUXWsAXOOaZw+h37N9gUc/XLw3KHwwDQYJKoZIhvcNAQEL
+BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMCAXDTIwMDEw
+NzA5MzQwOVoYDzk5OTkxMjMxMjM1OTU5WjAjMSEwHwYDVQQDExhLbm90IFJlc29s
+dmVyIHRlc3RpbmcgQ0EwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCe
+7vLYQa4sk4oBH4hb1oUpL5GdN/w1iH9TcYf8F3HnFVcGLVT7GZiAguwamS1Xy1/d
+KCbYlftlsr7hEYZpFH4yXMACC10ReGlQICU+FfuKRtGD+TuERpxpIUTVCR16BMzz
+aupMG9p8QN0cb/aFtOp1mDR5EfvP0xhwZCUzijG2k2fUMmdhHNB7hWFUxvtRtocd
+1LhYQKnFMs7guZA3DVjkM3DFxZHyGPXgCK0Xi89y8SZsnIjSngZMAl1OfJOvjXKT
+dR1gDPc0Cajm8oBKFIEkQEtFGYUurY6XTP/s0J/moLfAqaCt0gItE1Xz3/j58fM+
+NekIK9sRk1cTVca6xtf/feH6jEdd2r8xVoCqNJdDu57/0+YTqcKZScIe2vLH0tb3
+X3A2kS/qNumIRAijGgrA4EtIgprJcimcCSRjs8KfKvboOsRGA41wrhS7OtbGYpMk
+f7wKyKIgUzyfXBVFBT0bOBfU/mtqwhbzFHPCw8c24/H45SiETjfUaOiCcCBT/AEC
+AwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1Ud
+DgQWBBSSt9DE0Qfipz+Ce4eGau+f9DecyDANBgkqhkiG9w0BAQsFAAOCAYEAA45p
+Ak7ebzk2ss5FHhJDvHrhoTZG2/esNEQhtv70nuRPnm3j8UGDxYyydwjf4+W9DT1v
+53QNfvbOIPcOUsGArAItmI7K6ltkBSS6ymO8T1ZY4vYw+77jJZ1EeYS6kjdan7dK
+f2Zz23CVbuq8BOc/Ob6ChepEq/MIb3g/Y6FowuWqeC85s61GW9MKr5GeG0oSyYAO
+UZdFnwa8QLCZ2IzQcwnolkAw2A/5TDxovINy9Lb5U3kyphC9vhjPqr8PJ5q/KVuK
+vcHvEsrsSNPvW/WcxkziV1oJTnjvr/69mwAme8+xjjF90GhrNaQF1YOoijuZuQaS
+Q+0qmwZbsMtcqAABKQALHfLGsGAA5MKip49khIQWuIAS8P2vb+hzbqQRLjq1uW7B
+dEGvBHF0QebDZOXJeXEYK/b7btWa9kNedD2FvBx5c9QNiWwh7jZENkICKnhI7E+n
+d5/gsKVa1glKwbMagZBSJgFtjZe/eo/LcoK82m4VuOUCJSe0Kd0McrSZ7XZX
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/ca.tmpl b/daemon/lua/trust_anchors.test/x509/ca.tmpl
new file mode 100644
index 0000000..ed801af
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/ca.tmpl
@@ -0,0 +1,4 @@
+cn = Knot Resolver testing CA
+ca
+cert_signing_key
+expiration_days = -1
diff --git a/daemon/lua/trust_anchors.test/x509/gen.sh b/daemon/lua/trust_anchors.test/x509/gen.sh
new file mode 100755
index 0000000..7251f12
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/gen.sh
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# CA
+certtool --generate-privkey > ca-key.pem
+certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca.pem
+
+# server cert signed by CA above
+certtool --generate-privkey > server-key.pem
+certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server.pem
+
+# wrong CA - unrelated to others
+certtool --generate-privkey > wrongca-key.pem
+certtool --generate-self-signed --load-privkey wrongca-key.pem --template wrongca.tmpl --outfile wrongca.pem
diff --git a/daemon/lua/trust_anchors.test/x509/server-key.pem b/daemon/lua/trust_anchors.test/x509/server-key.pem
new file mode 100644
index 0000000..9eaef8a
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:c3:46:2a:27:c8:39:e4:de:fa:24:45:6c:00:26:80
+ 61:ca:dd:a1:24:34:1b:93:1c:13:c8:5a:cf:af:6a:ef
+ 34:b9:89:83:02:76:51:ad:67:bf:ed:39:ee:0a:15:57
+ 91:6e:fa:68:60:78:22:62:fa:0a:55:12:03:b3:0c:8e
+ b4:ca:cd:2b:9d:a2:43:b5:5a:48:a0:3d:4a:1f:77:a4
+ a6:d4:87:eb:79:99:df:d4:b4:a3:cf:91:03:a0:c5:82
+ 39:f5:75:20:4b:90:b9:3b:72:65:a7:75:39:a6:62:58
+ 65:b0:9c:40:5c:c7:c4:4c:d3:1e:cc:74:18:74:15:23
+ 44:fd:51:59:b2:b7:70:95:6b:a0:be:d5:e4:72:59:2b
+ df:a5:a2:06:c8:e1:bd:17:80:25:b3:cf:8e:e8:ad:b2
+ f7:04:b1:9e:b8:72:0b:c5:dc:cd:a5:b6:f5:c9:1a:eb
+ 63:78:75:9c:5d:c5:03:a9:4b:7b:d6:cd:5c:5f:8d:2e
+ d0:b4:0d:96:55:c7:1e:c7:ac:13:46:b8:ec:9c:36:b9
+ 6a:1d:f0:7c:41:00:c6:bd:1f:81:7e:1d:48:1d:59:bc
+ e2:61:a6:d1:2d:52:10:3f:63:93:a9:14:d8:03:27:21
+ b0:d4:07:24:78:04:2b:86:c8:2b:0f:eb:a7:b3:3e:e2
+ 81:62:2a:4a:07:d9:fd:f6:77:7f:50:88:ee:bb:7d:31
+ 53:a8:97:bf:30:07:37:41:e9:52:16:15:74:a8:64:ed
+ 93:46:38:56:b4:89:d9:0c:62:4b:64:a9:64:ff:fc:9a
+ d6:19:a7:84:98:28:04:b4:95:76:ac:4a:42:6a:fb:67
+ 5b:b4:37:e6:e6:e2:52:d3:e9:38:8b:76:10:55:f1:e6
+ 8e:d8:73:eb:17:d1:54:41:d4:5b:76:2d:70:7f:f5:0d
+ 7d:d2:d6:f8:05:33:18:ab:dd:10:8a:5b:21:ee:3d:78
+ 9d:cd:c9:c0:c6:98:4e:a6:0a:41:f0:97:91:83:c2:c8
+ 4b:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 23:88:1f:e1:8f:40:61:91:e5:28:36:6d:99:75:68:04
+ e3:5a:02:99:48:d5:ff:a5:ab:3f:d8:ae:53:b7:fc:80
+ b6:85:fc:0d:b5:a3:d5:0e:bc:d0:98:aa:e4:b0:cf:77
+ 4a:1f:4c:60:c9:5b:50:71:38:f2:13:ce:12:85:65:6e
+ 26:3c:c1:03:f4:e3:a7:1b:1f:7d:f0:c9:0d:02:c3:36
+ 0c:14:13:57:d4:14:f3:6a:4f:28:54:b5:b9:4a:57:10
+ de:c6:0a:33:55:c9:2e:b4:f9:24:48:63:4e:10:35:0f
+ 83:dc:5a:a5:c7:3f:c3:ce:e2:9a:c7:41:2f:d6:2c:cd
+ bf:de:4e:99:03:61:fb:fe:52:88:86:f9:03:89:90:3f
+ 28:af:5b:d6:af:a4:ad:a3:06:b9:3a:3a:41:c2:61:7f
+ 2b:1e:7a:c8:0b:10:73:57:63:20:15:33:91:fd:50:f9
+ 8f:90:ae:fc:2c:fe:26:8e:f2:a0:ba:4b:65:a3:95:f1
+ d8:30:d4:fa:8d:12:1b:8b:58:1d:66:10:cd:41:22:1e
+ b0:7a:f4:e6:0f:76:3f:0a:0f:9c:44:e2:19:cf:c6:4d
+ de:3a:f4:96:70:c7:e6:2d:98:27:0e:ac:3b:32:41:37
+ 4e:05:b2:22:af:7b:38:92:16:40:fb:5c:96:b0:86:da
+ 96:c6:77:c3:66:78:07:80:5c:2a:46:dc:9a:bf:fc:0c
+ 2f:ee:f7:a1:b3:77:b4:50:75:a2:b7:36:9d:28:73:ee
+ 7a:ab:a6:0c:f6:92:18:8f:ff:16:28:90:7f:16:4f:f1
+ 6d:77:99:dd:a6:46:95:6a:6c:7a:15:48:53:b3:17:0b
+ 30:aa:0d:c8:68:33:2b:4d:40:da:74:cf:9b:73:1b:cd
+ 5d:f0:a9:d1:00:6f:db:de:55:ec:d4:24:96:bb:da:50
+ b4:d5:e1:87:35:5c:d4:50:c3:03:d5:d5:ee:03:65:4b
+ 68:9c:07:5c:59:28:78:bd:d1:4b:cb:8d:85:8b:5b:c1
+
+
+prime1:
+ 00:cc:8d:55:38:2d:57:cb:d2:4b:57:5b:3f:a2:6d:91
+ 4b:9c:54:29:98:9d:1d:bb:36:a6:e8:ba:e9:50:db:83
+ cf:c1:45:24:16:70:e5:51:40:eb:23:6b:fa:be:d5:d5
+ 00:27:ed:99:c7:7c:6b:16:79:77:0b:f3:ff:58:35:4e
+ 6c:58:68:51:d3:20:3c:57:b7:7d:bc:6b:fd:a7:c3:38
+ 9a:f2:7a:8a:b6:71:a1:6e:5e:64:7e:a8:c5:7c:58:70
+ fb:8d:63:b3:27:cc:1a:97:1e:04:da:d5:34:b5:d1:aa
+ f1:96:39:89:5e:cb:e7:75:ab:7e:ac:8c:fe:62:3e:cc
+ 93:66:88:d7:cd:c6:2d:db:9e:2f:f7:d1:6e:96:99:d2
+ 32:61:f4:9b:f5:48:fe:e7:90:b7:a2:ab:89:90:c1:ae
+ 67:5d:18:7a:c1:a3:84:97:09:47:13:df:d2:85:46:46
+ c7:77:3b:9f:b5:74:5c:f6:ec:a0:a7:66:0e:d1:d7:a4
+ e1:
+
+prime2:
+ 00:f4:63:70:fa:dd:7e:3d:1a:2b:5b:47:79:56:e9:c7
+ 7f:6b:50:41:60:45:af:59:e0:77:b2:76:4e:40:ff:f8
+ 55:9d:77:3b:c1:00:6a:c6:84:6a:09:a5:45:e6:fc:e6
+ e6:92:72:32:fc:93:8f:93:d9:db:fc:8c:43:d2:7a:ea
+ 4b:0e:ee:1d:dc:e0:27:08:83:16:aa:de:37:59:39:c0
+ 21:26:b5:34:49:f2:1f:7b:0c:d4:3c:0f:e5:06:ac:23
+ 7b:85:b1:39:35:44:ec:70:48:c5:10:86:02:ea:36:4a
+ f1:20:a2:b2:c9:8d:d3:f6:5a:86:72:4b:8b:28:07:04
+ 39:8d:01:fa:75:3a:35:40:c2:21:c3:ac:50:da:2f:3e
+ 30:ee:ab:f7:7d:81:a3:77:5e:b7:03:be:52:fb:a4:70
+ 92:5d:fd:09:ae:52:33:b8:7b:9c:e2:2a:77:f7:23:4d
+ c5:4b:82:f1:fb:0a:09:62:e6:5f:32:1e:7b:c7:c6:66
+ ab:
+
+coefficient:
+ 00:c3:2d:d8:18:32:30:a1:fa:2c:23:d0:ea:b4:60:0f
+ 29:67:50:4a:5a:61:aa:6d:15:0e:4b:66:43:35:ee:39
+ 4c:e7:8d:31:73:b0:bb:04:4d:e5:bc:28:ea:dc:77:81
+ 35:bb:f7:80:13:96:04:4c:45:9c:43:6f:64:e0:a3:51
+ 4b:7e:6c:b6:7d:c2:a6:e0:94:e6:6c:34:4e:62:71:ea
+ c0:c0:ab:30:30:c1:3a:39:0e:cd:f0:cc:0e:31:b5:fc
+ 61:64:1e:29:1c:cd:fc:69:c0:02:7c:2a:fe:86:d5:e2
+ 7b:8d:fe:ae:3d:3a:6c:1b:b3:b4:0d:b1:1b:d1:4d:37
+ 36:ea:d7:15:f3:6e:02:b1:86:98:51:02:fc:62:df:30
+ f2:de:9f:03:6d:27:45:d7:c7:a8:04:ba:76:18:01:09
+ 34:d2:57:f9:10:50:ea:ae:0e:ae:c6:a4:cd:f9:fd:b1
+ 25:b2:45:20:bc:50:2d:9b:80:c1:39:08:97:d2:75:9b
+ f7:
+
+exp1:
+ 00:8a:b8:6a:8b:cf:8c:54:08:c8:d9:74:63:82:67:25
+ fb:0e:08:b1:b0:f3:14:7f:ab:3f:a4:63:65:e9:55:05
+ 5e:36:a7:0a:23:41:ea:f2:a0:c1:16:63:9b:48:22:41
+ f2:7a:21:93:81:8a:ea:20:f2:bc:fe:59:39:d8:fb:45
+ b5:0a:7b:ac:ca:2e:79:5d:cf:6d:b1:03:d7:a1:17:2e
+ e3:3e:00:46:e4:15:c9:b1:cc:c8:00:71:ba:84:6a:82
+ 2c:c6:a5:4f:91:74:c4:af:a9:47:07:95:41:ca:f0:67
+ 2a:b1:83:51:9a:fd:53:7a:24:94:a2:b6:77:a9:ef:06
+ d4:0b:dc:4f:e6:18:39:6f:50:27:1d:bc:65:70:32:df
+ 2f:15:e9:4a:7f:1d:42:e9:8d:e6:4b:a6:63:83:cd:25
+ d6:a9:76:f9:81:2a:c0:b7:a1:2e:17:d7:59:b0:d2:89
+ 1b:aa:cb:bf:b2:d2:38:5d:a8:fa:06:ac:9a:ee:4a:7d
+ 61:
+
+exp2:
+ 00:92:66:af:db:d8:ac:33:36:66:1a:bc:6a:78:22:7c
+ 1c:5c:d1:2b:18:dd:25:fa:95:79:9f:33:38:15:c0:41
+ a8:28:38:b1:57:21:44:d5:bf:a5:36:3a:07:f2:24:36
+ be:91:a4:4f:de:f7:16:df:df:76:e5:87:b1:69:79:b0
+ b9:5e:2c:4f:3f:6e:18:74:04:f3:a3:50:93:9f:a3:f4
+ f0:e7:1b:4e:43:ae:04:25:d6:bd:9d:6d:78:29:d3:1d
+ 3e:76:0c:80:d4:e4:81:2f:92:a8:5b:09:ac:dd:59:c0
+ f3:4a:35:ad:1d:09:15:9d:53:05:8f:9a:a9:b6:44:dd
+ c7:0c:2d:cf:38:42:b2:7c:24:cf:cd:44:80:fa:f3:aa
+ 31:ee:08:9e:ae:54:e6:f4:2f:8d:3b:74:dc:89:5b:2d
+ 04:c1:c1:3f:f7:69:cf:0a:09:23:26:69:82:8c:4e:5d
+ dc:7f:2b:e6:82:18:b5:1e:c6:1a:e9:0f:51:df:8f:7f
+ 19:
+
+
+Public Key PIN:
+ pin-sha256:pFSHHHovr50DJ04K3wEJcyxth+nszZdClOet/CRN9cU=
+Public Key ID:
+ sha256:a454871c7a2faf9d03274e0adf0109732c6d87e9eccd974294e7adfc244df5c5
+ sha1:5137ef343399ccf38d6566803ddce123da640553
+
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/server.pem b/daemon/lua/trust_anchors.test/x509/server.pem
new file mode 100644
index 0000000..b42f07e
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEfTCCAuWgAwIBAgIUIREQSLx52Sc9PFWI6Nwe3YzRp3MwDQYJKoZIhvcNAQEL
+BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMCAXDTIwMDEw
+NzA5MzQwOVoYDzk5OTkxMjMxMjM1OTU5WjA8MRIwEAYDVQQDEwlsb2NhbGhvc3Qx
+JjAkBgNVBAoTHUZha2UgRE5TIHJvb3Qgb3JnIHRlc3Qgc2VydmVyMIIBojANBgkq
+hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAw0YqJ8g55N76JEVsACaAYcrdoSQ0G5Mc
+E8haz69q7zS5iYMCdlGtZ7/tOe4KFVeRbvpoYHgiYvoKVRIDswyOtMrNK52iQ7Va
+SKA9Sh93pKbUh+t5md/UtKPPkQOgxYI59XUgS5C5O3Jlp3U5pmJYZbCcQFzHxEzT
+Hsx0GHQVI0T9UVmyt3CVa6C+1eRyWSvfpaIGyOG9F4Als8+O6K2y9wSxnrhyC8Xc
+zaW29cka62N4dZxdxQOpS3vWzVxfjS7QtA2WVccex6wTRrjsnDa5ah3wfEEAxr0f
+gX4dSB1ZvOJhptEtUhA/Y5OpFNgDJyGw1AckeAQrhsgrD+unsz7igWIqSgfZ/fZ3
+f1CI7rt9MVOol78wBzdB6VIWFXSoZO2TRjhWtInZDGJLZKlk//ya1hmnhJgoBLSV
+dqxKQmr7Z1u0N+bm4lLT6TiLdhBV8eaO2HPrF9FUQdRbdi1wf/UNfdLW+AUzGKvd
+EIpbIe49eJ3NycDGmE6mCkHwl5GDwshLAgMBAAGjgY0wgYowDAYDVR0TAQH/BAIw
+ADAUBgNVHREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
+VR0PAQH/BAUDAwegADAdBgNVHQ4EFgQUUTfvNDOZzPONZWaAPdzhI9pkBVMwHwYD
+VR0jBBgwFoAUkrfQxNEH4qc/gnuHhmrvn/Q3nMgwDQYJKoZIhvcNAQELBQADggGB
+AFfFgv5J1eb8h33tnvDJ/dLBSA7Soz1NXK8iha18CH1uxW2lo+6iJl7g191WD/3W
+m/LdpRU3h5ewbD6An3FSA0I25cYQD1vlH7vdI+xu3hIuFhQVnkxGbwISzlM5vat8
+1Ry7z/RpHmQA4V4z4R/PuYcQHQG5tINMPySmbfHBK/Ju+nnmSTJ/p3Z7sVaSCfNN
+l37me0w197QU3ovNtA61xHa77VUSJeaAC+zOOXUBZ8Rc5PqhYOf6AJbIBk7tPNei
+XH5Yyg3UT0i7V09vUViXK8EXbMX1VWsw59Et4Ro1YouS6TN34i2w8FtKg1+amQLr
+UXmQW1lkzx23FdGG4T0fFPtWuJCL6ioc0J6vS7xt0xkbrri9U2thC7gvrKLGCJ6J
+hWTGoKwjcBHpoLsT62XogHlctagkyXfjJ1Piik7k2JjqvmyteFlDDkOToLQmaCuI
+LIBmOnO9mEig3y7T72cnL8QM+nb+c70cssfCW3LBTHb893J4QAOt5RN6LQUlFc49
+sQ==
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/server.tmpl b/daemon/lua/trust_anchors.test/x509/server.tmpl
new file mode 100644
index 0000000..8021616
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/server.tmpl
@@ -0,0 +1,7 @@
+organization = Fake DNS root org test server
+cn = localhost
+tls_www_server
+encryption_key
+signing_key
+dns_name = localhost
+expiration_days = -1
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca-key.pem b/daemon/lua/trust_anchors.test/x509/wrongca-key.pem
new file mode 100644
index 0000000..1ddc1ad
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca-key.pem
@@ -0,0 +1,182 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:bb:d7:47:1f:55:ed:c0:08:af:1d:32:d2:69:ef:77
+ d2:f3:f6:86:7e:f3:97:e2:35:72:d4:0a:87:1e:75:76
+ bf:59:29:be:cd:e6:ad:6d:7d:62:47:19:fb:ed:24:94
+ 7f:2b:d6:0c:68:cf:cd:ee:f3:5e:b2:db:11:44:4b:7f
+ 30:ce:d2:a7:75:a7:37:83:c0:41:d6:a1:87:22:48:fa
+ ef:d1:15:ed:c9:d2:73:ab:e1:7c:94:4d:b2:96:80:cf
+ 5a:5c:7e:96:f6:02:fa:a4:8b:b1:05:b0:27:f5:d7:38
+ bd:20:37:ed:12:c0:22:07:a9:a6:5e:47:bd:1d:33:27
+ a2:cd:4c:0c:70:ba:6e:d9:13:6f:7b:a1:72:e8:f4:be
+ e3:86:1b:a2:b3:a1:07:cf:93:e8:3a:26:51:3e:af:bc
+ da:80:b1:92:56:8b:21:e7:1d:d9:f9:0c:a9:68:b7:04
+ d8:6d:1f:6f:98:90:fb:fb:35:18:71:3c:50:73:b1:45
+ b1:e7:ee:7b:84:5d:57:95:33:37:b0:0f:eb:85:8f:8d
+ b0:7f:10:17:80:03:99:1b:62:0c:1d:72:6f:e5:77:38
+ c8:75:96:61:36:4b:28:ae:17:a4:f9:81:90:4d:4b:85
+ 61:39:be:6c:ca:c0:a9:cd:4e:45:27:47:84:82:3d:7f
+ c6:a7:00:d7:90:64:7c:a5:e9:f8:f6:92:d2:72:54:a7
+ 95:5f:fc:93:1d:c9:1a:78:6e:3a:1a:1f:8f:a2:41:d2
+ 04:5c:19:32:54:16:f2:97:6f:7c:f9:24:d7:a6:e2:07
+ cf:9f:9e:64:27:81:5f:5a:77:65:4f:7b:b2:81:78:3f
+ a3:22:17:d3:ba:06:71:d5:09:6a:c2:85:ba:35:f7:71
+ 01:b4:63:c7:70:62:98:58:80:a2:40:27:c0:e2:d5:fd
+ 60:e0:5a:7a:9c:bf:7b:e6:34:78:f1:16:e8:28:d9:92
+ dc:e6:2e:b6:d7:1a:83:4b:86:92:d6:81:ce:8e:50:0a
+ d5:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 7a:27:5e:66:1f:60:54:60:91:58:80:a3:5b:26:d2:9a
+ 89:f2:88:b6:68:3d:1e:6b:39:b8:70:fc:3b:af:91:c0
+ 90:00:58:c7:d7:ba:72:98:76:5f:dc:a2:fb:2d:ad:b0
+ 21:d6:ba:0d:33:0e:2d:d5:70:81:09:7b:6a:19:5a:a6
+ 67:e9:8f:e3:30:12:27:08:d1:07:fd:d5:3e:53:8d:74
+ 85:59:28:60:f6:0e:28:f9:a3:25:62:7d:bf:e8:16:70
+ 21:f4:64:c1:a9:60:4b:bf:58:28:65:cd:26:cf:86:63
+ 5f:5f:5f:39:b1:5e:af:f3:00:71:11:60:07:6c:2b:db
+ 70:7c:83:1e:8f:ee:e4:16:02:8a:b8:8c:5c:b8:44:a6
+ fb:a0:5f:27:47:92:27:c8:7c:dd:cb:eb:4b:c3:c7:21
+ a5:4d:54:e8:18:e4:bc:42:aa:6c:8e:72:60:d9:9c:3a
+ 0e:84:c1:f2:ca:5e:43:97:dc:c4:4e:bf:d6:ec:b2:70
+ 08:41:13:01:48:bc:36:a2:eb:5e:67:b6:6a:a4:b6:4a
+ 24:fa:fd:6d:ef:5b:77:bc:0c:7d:95:9a:84:ec:3f:97
+ aa:7c:07:76:80:f5:3a:49:f4:99:ee:cf:17:12:83:e8
+ db:ef:22:60:67:62:f8:3e:f9:bc:18:2b:84:fc:a9:82
+ 95:8d:91:27:8e:ba:87:15:65:1e:9f:b3:95:5f:dc:40
+ 2f:15:eb:7e:0a:d7:69:80:7b:8a:e2:29:89:3a:2e:eb
+ a9:05:c1:1e:5d:23:0d:a0:d7:c4:95:4d:09:85:8c:af
+ 90:23:36:04:66:a9:16:d7:d4:e2:aa:5a:6d:44:5a:6c
+ c8:e8:a0:08:fa:de:19:20:5f:e3:06:17:e5:65:c6:55
+ ef:0f:0d:ff:3e:1c:c5:98:ee:34:d3:07:81:11:fe:e9
+ 15:87:e6:9a:76:44:bd:cb:a0:38:63:9a:af:d1:7c:a7
+ db:26:e2:cd:4a:a2:8a:7f:b8:dc:7a:55:00:4c:20:c1
+
+
+prime1:
+ 00:c9:f5:14:59:49:3b:95:1f:15:b0:0c:83:cb:f4:6a
+ 48:60:2a:af:8b:d5:83:16:aa:71:5a:af:11:63:c6:c1
+ 0a:91:af:5b:bd:6e:9c:cb:d7:eb:bf:c7:31:9f:22:46
+ 01:cf:3b:3c:cb:ba:7d:ad:e5:bb:d8:7c:d2:5d:52:20
+ 14:ea:70:08:9e:29:98:31:20:78:9e:b6:3e:90:e8:ef
+ c8:2f:45:d4:35:04:71:a1:84:18:50:a9:a5:12:b7:14
+ 4e:42:3e:93:50:9d:2f:c1:bd:45:f3:4e:86:61:0b:bc
+ 3b:ed:78:c7:2b:ba:4b:a0:ef:e6:0e:a9:9a:f4:aa:73
+ 23:b8:51:c7:d3:dd:fd:a7:1c:c1:69:32:ea:26:32:6d
+ 40:b0:0a:cd:0d:fa:b4:f4:56:ed:e8:d4:96:08:80:fd
+ 43:44:8c:fb:bb:af:81:d7:bb:71:c6:7c:3a:d2:a7:83
+ e6:28:2d:2f:00:05:82:d7:cc:59:db:d9:e5:4f:a4:67
+ 05:
+
+prime2:
+ 00:ee:1b:2a:48:37:fa:7c:94:35:36:ac:83:5f:2c:98
+ e3:07:43:d1:2c:80:0e:a2:b8:7a:eb:e2:70:f6:49:77
+ b3:42:05:fe:06:cf:3f:ca:0f:0d:44:1c:74:0a:77:f7
+ 31:9f:30:fb:d9:44:71:11:e6:4a:ff:ef:ae:77:98:3e
+ 73:a0:77:21:a6:e0:66:9a:cf:5f:eb:3b:39:62:0b:ba
+ 1b:9b:1a:a5:58:4c:7e:17:fc:64:61:93:89:f0:c0:0f
+ ce:55:18:7e:d4:33:87:32:0e:53:51:5f:03:b4:05:4a
+ 5c:e7:5b:10:e5:b7:88:e5:04:b2:53:45:98:2f:9d:fb
+ 32:f5:2f:d9:59:54:ce:91:83:4c:37:ee:ab:5a:05:40
+ 85:05:03:ae:b4:3d:96:c2:67:6b:28:25:91:87:ed:d1
+ 3a:0f:4b:38:a5:81:b3:5b:6f:3e:33:27:1e:9a:4a:e6
+ 3c:7c:be:9f:45:72:5b:eb:e3:dd:6c:73:ae:0d:07:bd
+ 91:
+
+coefficient:
+ 45:53:87:ab:71:9c:14:af:6c:00:44:bb:de:d5:72:ed
+ e9:21:f2:19:e5:4d:30:92:8e:9b:b7:f6:db:9e:ea:71
+ b3:c2:89:01:4a:49:1f:2e:f8:34:57:e0:36:9a:20:84
+ a8:b0:8a:0b:2a:d6:da:36:22:c2:ac:a2:85:99:f7:5d
+ 3f:2e:71:ab:e5:f7:bd:b2:8c:6f:44:33:aa:2d:cf:38
+ 8c:d6:77:c7:d5:68:88:f1:f9:80:c2:e2:b8:58:26:bd
+ de:d6:8d:d5:c9:43:dc:e2:af:2e:d3:c5:19:4e:d5:14
+ 33:bc:15:58:6f:05:eb:8d:0d:fa:40:a3:b7:77:24:4b
+ 30:a7:c2:8b:89:08:24:4d:fb:2e:3c:ad:ff:e3:d7:8b
+ 9c:f2:07:0d:79:3c:5e:f5:83:94:32:e2:16:dc:a9:22
+ b4:f4:09:6a:f6:af:7d:9c:41:dc:be:23:7e:c4:6d:d6
+ f9:e6:8e:3c:2d:00:fa:ac:d2:c8:6e:c5:6d:52:74:cd
+
+
+exp1:
+ 4d:20:f9:2d:84:47:6a:13:1e:10:47:27:4a:8c:44:ce
+ f1:53:3c:09:d6:78:22:fe:e3:1d:b4:00:9b:2f:7b:e8
+ 12:6d:7b:46:e4:68:a3:7d:09:ff:0b:0f:0b:6c:66:7a
+ 28:6f:c2:2f:38:40:e9:59:f4:9c:a0:47:22:f6:cb:63
+ d1:89:09:f1:85:87:27:33:f4:7d:00:b2:f2:5a:d3:c0
+ 8b:35:4a:ef:18:8c:61:17:f6:c5:4f:94:c8:89:fd:0a
+ 4a:48:65:b0:82:e7:8b:41:42:e6:c2:15:96:18:8a:42
+ 04:d6:7c:92:59:aa:aa:83:14:44:83:47:b7:ab:25:1f
+ fe:33:d5:72:37:b4:b8:ce:c5:9a:ec:a3:fa:04:86:2f
+ 0f:4c:80:b5:97:0a:e6:ca:10:40:3c:78:34:35:37:04
+ 2a:b9:01:26:d3:c7:6d:e1:9b:79:27:56:bb:be:d8:23
+ dd:32:2c:62:00:b8:d0:bb:ad:91:c6:2c:ca:76:ca:15
+
+
+exp2:
+ 30:d8:19:c0:5e:db:5f:9a:f7:9f:93:9c:0f:76:12:96
+ df:f2:a5:82:3f:72:c1:26:9e:f0:ac:af:07:96:e2:9b
+ 3f:3c:03:74:5a:27:77:c7:c6:ac:e6:39:57:bc:6c:55
+ 1d:96:ea:d3:13:1b:2e:d4:d3:25:d5:81:30:bf:66:70
+ 49:c6:a6:7c:99:23:f3:35:ff:33:3e:1e:f3:61:fc:77
+ 95:45:ce:0d:63:03:aa:df:f7:a7:9c:a0:7b:66:aa:d7
+ 64:d5:75:8f:0a:52:fd:8d:ba:c1:c2:7f:fb:f9:e9:db
+ 4d:0a:7d:58:e2:61:8e:b9:7b:eb:61:27:6a:fd:39:7e
+ a6:95:7e:3c:b9:0c:f7:04:bc:29:ed:27:f1:7b:8a:54
+ bf:46:96:1c:1b:56:45:e2:f9:34:6f:20:7f:85:e5:99
+ c7:71:62:d9:70:d5:de:37:df:c6:96:8b:cc:92:f8:d0
+ 07:b7:02:ed:38:1c:6b:33:7f:44:b4:26:4c:3d:fe:41
+
+
+
+Public Key PIN:
+ pin-sha256:UOonm3sEw21t/nC/tr24q9sX/HPV9mo0/M3Ya8rAwLs=
+Public Key ID:
+ sha256:50ea279b7b04c36d6dfe70bfb6bdb8abdb17fc73d5f66a34fccdd86bcac0c0bb
+ sha1:b963cfb8eb202ccad2bb988dfa9e00cc52c1a4ba
+
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca.pem b/daemon/lua/trust_anchors.test/x509/wrongca.pem
new file mode 100644
index 0000000..fc3e43f
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEETCCAnmgAwIBAgIUNVTN+if8IQU0I1n4qyVF9qqhuo0wDQYJKoZIhvcNAQEL
+BQAwHzEdMBsGA1UEAxMUQW5vdGhlciB1bnJlbGF0ZWQgQ0EwIBcNMjAwMTA3MDkz
+NDA5WhgPOTk5OTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFEFub3RoZXIgdW5yZWxh
+dGVkIENBMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu9dHH1XtwAiv
+HTLSae930vP2hn7zl+I1ctQKhx51dr9ZKb7N5q1tfWJHGfvtJJR/K9YMaM/N7vNe
+stsRREt/MM7Sp3WnN4PAQdahhyJI+u/RFe3J0nOr4XyUTbKWgM9aXH6W9gL6pIux
+BbAn9dc4vSA37RLAIgeppl5HvR0zJ6LNTAxwum7ZE297oXLo9L7jhhuis6EHz5Po
+OiZRPq+82oCxklaLIecd2fkMqWi3BNhtH2+YkPv7NRhxPFBzsUWx5+57hF1XlTM3
+sA/rhY+NsH8QF4ADmRtiDB1yb+V3OMh1lmE2SyiuF6T5gZBNS4VhOb5sysCpzU5F
+J0eEgj1/xqcA15BkfKXp+PaS0nJUp5Vf/JMdyRp4bjoaH4+iQdIEXBkyVBbyl298
++STXpuIHz5+eZCeBX1p3ZU97soF4P6MiF9O6BnHVCWrChbo193EBtGPHcGKYWICi
+QCfA4tX9YOBaepy/e+Y0ePEW6CjZktzmLrbXGoNLhpLWgc6OUArVAgMBAAGjQzBB
+MA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4EFgQUuWPP
+uOsgLMrSu5iN+p4AzFLBpLowDQYJKoZIhvcNAQELBQADggGBAEobHXRbd6wfUmyf
+P5v6qdJQMqtNGlU8eYzizEyuyovSlL+g9wgQ/91RAYK26FXzOuRz9Cg/ZWYVHqiG
+rRWWwcfzY7qHo3HGkpDSIjD53TAoK46ICD4+EreG+JBvy1P3Ij/VX7M07swIg8Ff
+6O4CnJpKAFaSr9wT8Ac3oCu+vymgLajMocNYV/UFVND+TLi6sx0zcMfCgW2vhSWk
+PRulxL76xq97vjWoveqDiFS41cPOAghd4hUmzRFByX6XPBx6YZddSUF+QZt92K4Z
+YEU4UbKqhbiBoZMGaQ8DzM2T44WPISrRZ0QpeS+pXwVjbDfoUbBWYAjFA8EHhPOi
+oewIIYnarItI3z3iccErOeKPPVQh5QW3/CwO4XSnvTEBkhf2EjG25UAHZ8LZy0t8
+Sw1raGJPYJV/qNVeIzLKd3tYmNpcmddYqS+ei2yBOoO5UPdbYaH1gTAZ4BbOhOml
+BJKJWcekpJrZAVTBNRectxsMXB8fHYL65Wa+w3cRqsZRjTbTEg==
+-----END CERTIFICATE-----
diff --git a/daemon/lua/trust_anchors.test/x509/wrongca.tmpl b/daemon/lua/trust_anchors.test/x509/wrongca.tmpl
new file mode 100644
index 0000000..0e8491b
--- /dev/null
+++ b/daemon/lua/trust_anchors.test/x509/wrongca.tmpl
@@ -0,0 +1,4 @@
+cn = Another unrelated CA
+ca
+cert_signing_key
+expiration_days = -1