summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto
diff options
context:
space:
mode:
authorjsing <>2020-07-14 18:27:28 +0000
committerjsing <>2020-07-14 18:27:28 +0000
commitf133c373915d3c0ab63b4365469c5023561f3443 (patch)
tree8adad7e0ea025db74f93d91fc64fd242671ca862 /src/regress/lib/libcrypto
parent02b2b8724bbd999e01f85ef375fb6611f378d302 (diff)
downloadopenbsd-f133c373915d3c0ab63b4365469c5023561f3443.tar.gz
openbsd-f133c373915d3c0ab63b4365469c5023561f3443.tar.bz2
openbsd-f133c373915d3c0ab63b4365469c5023561f3443.zip
Provide tools to build certificate changes for verify regress.
This provides a script that generates a variety of certificate chains and assembles them into bundles containing various permutations, which can be used to test our X.509 verification. A Go program is included to verify each of these bundles. ok beck@ tb@
Diffstat (limited to 'src/regress/lib/libcrypto')
-rw-r--r--src/regress/lib/libcrypto/certs/Makefile21
-rw-r--r--src/regress/lib/libcrypto/certs/README123
-rw-r--r--src/regress/lib/libcrypto/certs/make-certs.sh381
-rw-r--r--src/regress/lib/libcrypto/certs/verify_test.go111
4 files changed, 636 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/certs/Makefile b/src/regress/lib/libcrypto/certs/Makefile
new file mode 100644
index 0000000000..621c60907f
--- /dev/null
+++ b/src/regress/lib/libcrypto/certs/Makefile
@@ -0,0 +1,21 @@
1# $OpenBSD: Makefile,v 1.1 2020/07/14 18:27:28 jsing Exp $
2
3.if ! (make(clean) || make(cleandir) || make(obj))
4GO_VERSION != sh -c "(go version) 2>/dev/null || true"
5.endif
6
7.if empty(GO_VERSION)
8regress:
9 @echo package go is required for this regress
10 @echo SKIPPED
11.endif
12
13REGRESS_TARGETS=regress-go-verify
14
15certs:
16 cd ${.CURDIR} && sh ./make-certs.sh
17
18regress-go-verify:
19 cd ${.CURDIR} && go test -test.v .
20
21.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/certs/README b/src/regress/lib/libcrypto/certs/README
new file mode 100644
index 0000000000..0d6fa7d48a
--- /dev/null
+++ b/src/regress/lib/libcrypto/certs/README
@@ -0,0 +1,123 @@
1This directory contains tools for building certificate chains to
2test verification. Each subdirectory contains a set of certificates
3that test a particular scenario. The root certificate(s) are contained
4in a roots.pem file, while the leaf certificate and any untrusted
5intermediate certificates are contained in a bundle.pem file.
6
7 1a. A leaf certificate signed by the root certificate with no
8 intermediates (should verify).
9
10 2a. A leaf certificate signed by an intermediate, which is signed
11 by a root certificate (should verify).
12
13 2b. Same as (2a), however the intermediate is missing which should
14 prevent verification.
15
16 3a. A leaf certificate signed by three intermediates, the last of
17 which is signed by a root certificate (should verify).
18
19 3b. Same as (3a) however the first intermediate is missing which should
20 prevent verification.
21
22 3c. Same as (3a) however the second intermediate is missing which should
23 prevent verification.
24
25 3d. Same as (3a) however the third intermediate is missing which should
26 prevent verification.
27
28 3e. Same as (3a) however the order of the intermediates is reversed
29 (should verify).
30
31 4a. A leaf certificate signed by an intermediate, that is cross
32 signed by two root certificates (should verify with two chains).
33
34 4b. Same as (4a) but with one root missing (should verify with one chain).
35
36 4c. Same as (4b) but with the other root missing (should verify with one
37 chain).
38
39 4d. Same as (4a) but with one intermediate missing (should verify with one
40 chain).
41
42 4e. Same as (4d) but with the other intermediate missing (should verify
43 with one chain).
44
45 4f. Same as (4a) but with the intermediates reversed (should verify with
46 two chains).
47
48 4g. Same as (4b) but with the intermediates reversed (should verify with
49 one chain).
50
51 4h. Same as (4c) but with the intermediates reversed (should verify with
52 one chain).
53
54 5a. A leaf certificate signed by an intermediate, that is cross
55 signed by one root certificate and an intermediate, which in turn
56 is signed by a second root (should verify with two chains).
57
58 5b. Same as (5a) but missing the first root certificate (should verify
59 with one chain).
60
61 5c. Same as (5a) but missing the second root certificate (should verify
62 with one chain).
63
64 5d. Same as (5a) but missing the first intermediate (should verify with
65 one chain).
66
67 5e. Same as (5a) but missing the second intermediate (should verify
68 with one chain).
69
70 5f. Same as (5a) but missing the cross-signed intermediate (should verify
71 with one chain).
72
73 5g. Same as (5a) but order of intermediates is reversed (should verify
74 with two chains).
75
76 5h. Same as (5g) but missing the first root certificate (should verify
77 with two chains).
78
79 5i. Same as (5g) but missing the second root certificate (should verify
80 with two chains).
81
82 6a. A leaf certificate signed by an intermediate, that is cross
83 signed by an expired root certificate and an intermediate, which
84 in turn is signed by a second root (should verify with one chain).
85
86 6b. Same as (6a) but the order of the intermediates is reversed (should
87 verify with one chain).
88
89 7a. A leaf certificate signed by an intermediate, that is cross
90 signed by a root certificate and an intermediate, which in turn
91 is signed by a second root that has expired (should verify with one
92 chain).
93
94 7b. Same as (7a) but the order of the intermediates is reversed (should
95 verify with one chain).
96
97 8a. An expired leaf certificate signed by an intermediate that is then
98 signed by a root certificate (should fail to verify).
99
100 9a. A leaf certificate signed by an expired intermediate, which is
101 signed by a root certificate (should fail to verify).
102
10310a. A leaf certificate signed by an intermediate, that is cross
104 signed by two root certificates, with one of the cross signings
105 having expired (should verify with one chain).
106
10710b. Same as (10a) but order of intermediates is reversed (should verify
108 with one chain.
109
11011a. A leaf certificate signed by an intermediate, that is cross
111 signed by one root certificate and an expired intermediate, which
112 in turn is signed by a second root (should verify with one chain).
113
11411b. Same as (11a) but order of intermediates is reversed (should verify
115 with one chain.
116
11712a. A leaf certificate signed by an intermediate, that is signed by a
118 root certificate and cross signed as an expired intermediate, by a
119 second root (should verify with one chain).
120
12113a. A leaf certificate signed by an intermediate, that is signed by an
122 expired root certificate and cross signed as an intermediate, by a
123 second root (should verify with one chain).
diff --git a/src/regress/lib/libcrypto/certs/make-certs.sh b/src/regress/lib/libcrypto/certs/make-certs.sh
new file mode 100644
index 0000000000..b34a547ba2
--- /dev/null
+++ b/src/regress/lib/libcrypto/certs/make-certs.sh
@@ -0,0 +1,381 @@
1#!/bin/ksh
2
3#
4# Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
5#
6# Permission to use, copy, modify, and distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17#
18
19set -e
20set -u
21set -x
22
23readonly SUBJECT="/CN=LibreSSL Test"
24
25readonly TMPDIR=$(mktemp -d)
26
27cleanup() {
28 rm -rf "${TMPDIR}"
29}
30
31trap cleanup EXIT INT
32
33reset() {
34 echo '100001' > ${TMPDIR}/certserial
35 cat /dev/null > ${TMPDIR}/certindex
36}
37
38setup() {
39 reset
40
41 cat > ${TMPDIR}/openssl.cnf <<EOF
42[ca]
43default_ca = test_ca
44
45[test_ca]
46new_certs_dir = ${TMPDIR}/
47database = ${TMPDIR}/certindex
48default_days = 365
49default_md = sha256
50policy = test_policy
51serial = ${TMPDIR}/certserial
52
53[test_policy]
54countryName = optional
55stateOrProvinceName = optional
56localityName = optional
57organizationName = optional
58organizationalUnitName = optional
59commonName = supplied
60emailAddress = optional
61
62[v3_ca_root]
63subjectKeyIdentifier = hash
64authorityKeyIdentifier = keyid:always,issuer
65basicConstraints = critical, CA:true
66keyUsage = critical, cRLSign, keyCertSign
67
68[v3_ca_int]
69subjectKeyIdentifier = hash
70authorityKeyIdentifier = keyid:always,issuer
71basicConstraints = critical, CA:true
72keyUsage = critical, cRLSign, keyCertSign
73
74[v3_other]
75subjectKeyIdentifier = hash
76authorityKeyIdentifier = keyid:always,issuer
77basicConstraints = critical, CA:false
78keyUsage = critical, digitalSignature
79
80[req]
81distinguished_name = req_distinguished_name
82
83[ req_distinguished_name ]
84EOF
85}
86
87create_root() {
88 local name=$1 file=$2
89
90 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 -x509 \
91 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
92 -config ${TMPDIR}/openssl.cnf -extensions v3_ca_root \
93 -out "${TMPDIR}/${file}.crt"
94}
95
96create_expired_root() {
97 local name=$1 file=$2
98
99 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
100 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
101 -config ${TMPDIR}/openssl.cnf -extensions v3_ca_root \
102 -out "${TMPDIR}/${file}.csr"
103 openssl ca -batch -notext -selfsign \
104 -keyfile "${TMPDIR}/${file}.key" \
105 -startdate 20100101000000Z -enddate 20200101000000Z \
106 -config ${TMPDIR}/openssl.cnf -extensions v3_ca_root \
107 -in "${TMPDIR}/${file}.csr" -out "${TMPDIR}/${file}.crt"
108}
109
110create_intermediate() {
111 local name=$1 file=$2 issuer_file=$3
112
113 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
114 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
115 -out "${TMPDIR}/${file}.csr"
116 openssl x509 -req -days 3650 -CA "${TMPDIR}/${issuer_file}.crt" \
117 -CAkey "${TMPDIR}/${issuer_file}.key" -CAcreateserial \
118 -extfile ${TMPDIR}/openssl.cnf -extensions v3_ca_int \
119 -in "${TMPDIR}/${file}.csr" -out "${TMPDIR}/${file}.crt"
120}
121
122create_expired_intermediate() {
123 local name=$1 file=$2 issuer_file=$3
124
125 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
126 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
127 -out "${TMPDIR}/${file}.csr"
128 openssl ca -batch -notext -cert "${TMPDIR}/${issuer_file}.crt" \
129 -keyfile "${TMPDIR}/${issuer_file}.key" \
130 -startdate 20100101000000Z -enddate 20200101000000Z \
131 -config ${TMPDIR}/openssl.cnf -extensions v3_ca_int \
132 -in "${TMPDIR}/${file}.csr" -out "${TMPDIR}/${file}.crt"
133}
134
135create_leaf() {
136 local name=$1 file=$2 issuer_file=$3
137
138 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
139 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
140 -out "${TMPDIR}/${file}.csr"
141 openssl x509 -req -days 3650 -CA "${TMPDIR}/${issuer_file}.crt" \
142 -CAkey "${TMPDIR}/${issuer_file}.key" -CAcreateserial \
143 -extfile ${TMPDIR}/openssl.cnf -extensions v3_other \
144 -in "${TMPDIR}/${file}.csr" -out "${TMPDIR}/${file}.crt"
145}
146
147create_expired_leaf() {
148 local name=$1 file=$2 issuer_file=$3
149
150 openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
151 -subj "${SUBJECT} ${name}" -keyout "${TMPDIR}/${file}.key" \
152 -out "${TMPDIR}/${file}.csr"
153 openssl ca -batch -notext -cert "${TMPDIR}/${issuer_file}.crt" \
154 -keyfile "${TMPDIR}/${issuer_file}.key" \
155 -config ${TMPDIR}/openssl.cnf -extensions v3_other \
156 -startdate 20100101000000Z -enddate 20200101000000Z \
157 -in "${TMPDIR}/${file}.csr" -out "${TMPDIR}/${file}.crt"
158}
159
160create_cross_signed() {
161 local file=$1 csr_file=$2 issuer_file=$3
162
163 openssl x509 -req -days 3650 -CA "${TMPDIR}/${issuer_file}.crt" \
164 -CAkey "${TMPDIR}/${issuer_file}.key" -CAcreateserial \
165 -extfile ${TMPDIR}/openssl.cnf -extensions v3_ca_int \
166 -in "${TMPDIR}/${csr_file}.csr" -out "${TMPDIR}/${file}.crt"
167}
168
169create_expired_cross_signed() {
170 local file=$1 csr_file=$2 issuer_file=$3
171
172 openssl ca -batch -notext -cert "${TMPDIR}/${issuer_file}.crt" \
173 -keyfile "${TMPDIR}/${issuer_file}.key" \
174 -startdate 20100101000000Z -enddate 20200101000000Z \
175 -config ${TMPDIR}/openssl.cnf -extensions v3_ca_int \
176 -in "${TMPDIR}/${csr_file}.csr" -out "${TMPDIR}/${file}.crt"
177}
178
179create_bundle() {
180 local bundle_file=$1
181 shift
182
183 mkdir -p $(dirname ${bundle_file})
184 cat /dev/null > ${bundle_file}
185
186 for _cert_file in $@; do
187 openssl x509 -nameopt oneline -subject -issuer -noout \
188 -in "${TMPDIR}/${_cert_file}.crt" >> ${bundle_file}
189 done
190 for _cert_file in $@; do
191 cat "${TMPDIR}/${_cert_file}.crt" >> ${bundle_file}
192 done
193}
194
195create_root_bundle() {
196 local bundle_file=$1
197 shift
198
199 mkdir -p $(dirname ${bundle_file})
200 cat /dev/null > ${bundle_file}
201
202 for _cert_file in $@; do
203 openssl x509 -nameopt oneline -subject -issuer \
204 -in "${TMPDIR}/${_cert_file}.crt" >> ${bundle_file}
205 done
206}
207
208setup
209
210# Scenario 1a.
211reset
212create_root "Root CA 1" "ca-root"
213create_leaf "Server 1" "server-1" "ca-root"
214create_root_bundle "./1a/roots.pem" "ca-root"
215create_bundle "./1a/bundle.pem" "server-1"
216
217# Scenarios 2a and 2b.
218reset
219create_root "Root CA 1" "ca-root"
220create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root"
221create_leaf "Server 1" "server-1" "ca-int-1"
222create_root_bundle "./2a/roots.pem" "ca-root"
223create_bundle "./2a/bundle.pem" "server-1" "ca-int-1"
224create_root_bundle "./2b/roots.pem" "ca-root"
225create_bundle "./2b/bundle.pem" "server-1"
226
227# Scenarios 3a, 3b, 3c, 3d and 3e.
228reset
229create_root "Root CA 1" "ca-root"
230create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root"
231create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
232create_intermediate "Intermediate CA 3" "ca-int-3" "ca-int-2"
233create_leaf "Server 1" "server-1" "ca-int-3"
234create_root_bundle "./3a/roots.pem" "ca-root"
235create_bundle "./3a/bundle.pem" "server-1" "ca-int-3" "ca-int-2" "ca-int-1"
236create_root_bundle "./3b/roots.pem" "ca-root"
237create_bundle "./3b/bundle.pem" "server-1" "ca-int-3" "ca-int-2"
238create_root_bundle "./3c/roots.pem" "ca-root"
239create_bundle "./3c/bundle.pem" "server-1" "ca-int-3" "ca-int-1"
240create_root_bundle "./3d/roots.pem" "ca-root"
241create_bundle "./3d/bundle.pem" "server-1" "ca-int-2" "ca-int-1"
242create_root_bundle "./3e/roots.pem" "ca-root"
243create_bundle "./3e/bundle.pem" "server-1" "ca-int-1" "ca-int-2" "ca-int-3"
244
245# Scenarios 4a, 4b, 4c, 4d, 4e, 4f, 4g and 4h.
246reset
247create_root "Root CA 1" "ca-root-1"
248create_root "Root CA 2" "ca-root-2"
249create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
250create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2"
251create_leaf "Server 1" "server-1" "ca-int-1"
252create_root_bundle "./4a/roots.pem" "ca-root-1" "ca-root-2"
253create_bundle "./4a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs"
254create_root_bundle "./4b/roots.pem" "ca-root-1"
255create_bundle "./4b/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs"
256create_root_bundle "./4c/roots.pem" "ca-root-2"
257create_bundle "./4c/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs"
258create_root_bundle "./4d/roots.pem" "ca-root-1" "ca-root-2"
259create_bundle "./4d/bundle.pem" "server-1" "ca-int-1"
260create_root_bundle "./4e/roots.pem" "ca-root-1" "ca-root-2"
261create_bundle "./4e/bundle.pem" "server-1" "ca-int-1-xs"
262create_root_bundle "./4f/roots.pem" "ca-root-1" "ca-root-2"
263create_bundle "./4f/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1"
264create_root_bundle "./4g/roots.pem" "ca-root-1"
265create_bundle "./4g/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1"
266create_root_bundle "./4h/roots.pem" "ca-root-2"
267create_bundle "./4h/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1"
268
269# Scenario 5a, 5b, 5c, 5d, 5e, 5f, 5g, 5h and 5i.
270reset
271create_root "Root CA 1" "ca-root-1"
272create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
273create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
274create_root "Root CA 2" "ca-root-2"
275create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2"
276create_leaf "Server 1" "server-1" "ca-int-2"
277create_root_bundle "./5a/roots.pem" "ca-root-1" "ca-root-2"
278create_bundle "./5a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
279create_root_bundle "./5b/roots.pem" "ca-root-2"
280create_bundle "./5b/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
281create_root_bundle "./5c/roots.pem" "ca-root-1"
282create_bundle "./5c/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
283create_root_bundle "./5d/roots.pem" "ca-root-1" "ca-root-2"
284create_bundle "./5d/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-1"
285create_root_bundle "./5e/roots.pem" "ca-root-1" "ca-root-2"
286create_bundle "./5e/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs"
287create_root_bundle "./5f/roots.pem" "ca-root-1" "ca-root-2"
288create_bundle "./5f/bundle.pem" "server-1" "ca-int-2" "ca-int-1"
289create_root_bundle "./5g/roots.pem" "ca-root-1" "ca-root-2"
290create_bundle "./5g/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
291create_root_bundle "./5h/roots.pem" "ca-root-2"
292create_bundle "./5h/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
293create_root_bundle "./5i/roots.pem" "ca-root-1"
294create_bundle "./5i/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
295
296# Scenarios 6a and 6b.
297reset
298create_root "Root CA 1" "ca-root-1"
299create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
300create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
301create_expired_root "Root CA 2" "ca-root-2"
302create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2"
303create_leaf "Server 1" "server-1" "ca-int-2"
304create_root_bundle "./6a/roots.pem" "ca-root-1" "ca-root-2"
305create_bundle "./6a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
306create_root_bundle "./6b/roots.pem" "ca-root-1" "ca-root-2"
307create_bundle "./6b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
308
309# Scenarios 7a and 7b.
310reset
311create_expired_root "Root CA 1" "ca-root-1"
312create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
313create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
314create_root "Root CA 2" "ca-root-2"
315create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2"
316create_leaf "Server 1" "server-1" "ca-int-2"
317create_root_bundle "./7a/roots.pem" "ca-root-1" "ca-root-2"
318create_bundle "./7a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
319create_root_bundle "./7b/roots.pem" "ca-root-1" "ca-root-2"
320create_bundle "./7b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
321
322# Scenario 8a.
323reset
324create_root "Root CA 1" "ca-root"
325create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root"
326create_expired_leaf "Server 1" "server-1" "ca-int-1"
327create_root_bundle "./8a/roots.pem" "ca-root"
328create_bundle "./8a/bundle.pem" "server-1" "ca-int-1"
329
330# Scenario 9a.
331reset
332create_root "Root CA 1" "ca-root"
333create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root"
334create_leaf "Server 1" "server-1" "ca-int-1"
335create_root_bundle "./9a/roots.pem" "ca-root"
336create_bundle "./9a/bundle.pem" "server-1" "ca-int-1"
337
338# Scenarios 10a and 10b.
339reset
340create_root "Root CA 1" "ca-root-1"
341create_root "Root CA 2" "ca-root-2"
342create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
343create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2"
344create_leaf "Server 1" "server-1" "ca-int-1"
345create_root_bundle "./10a/roots.pem" "ca-root-1" "ca-root-2"
346create_bundle "./10a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs"
347create_root_bundle "./10b/roots.pem" "ca-root-1" "ca-root-2"
348create_bundle "./10b/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1"
349
350# Scenarios 11a and 11b.
351reset
352create_root "Root CA 1" "ca-root-1"
353create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
354create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
355create_root "Root CA 2" "ca-root-2"
356create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2"
357create_leaf "Server 1" "server-1" "ca-int-2"
358create_root_bundle "./11a/roots.pem" "ca-root-1" "ca-root-2"
359create_bundle "./11a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1"
360create_root_bundle "./11b/roots.pem" "ca-root-1" "ca-root-2"
361create_bundle "./11b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1"
362
363# Scenario 12a.
364reset
365create_root "Root CA 1" "ca-root-1"
366create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
367create_cross_signed "ca-root-2" "ca-int-1" "ca-root-1"
368create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
369create_leaf "Server 1" "server-1" "ca-int-2"
370create_root_bundle "./12a/roots.pem" "ca-root-1" "ca-root-2"
371create_bundle "./12a/bundle.pem" "server-1" "ca-int-2" "ca-int-1"
372
373# Scenario 13a.
374reset
375create_root "Root CA 1" "ca-root-1"
376create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1"
377create_expired_cross_signed "ca-root-2" "ca-int-1" "ca-root-1"
378create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1"
379create_leaf "Server 1" "server-1" "ca-int-2"
380create_root_bundle "./13a/roots.pem" "ca-root-1" "ca-root-2"
381create_bundle "./13a/bundle.pem" "server-1" "ca-int-2" "ca-int-1"
diff --git a/src/regress/lib/libcrypto/certs/verify_test.go b/src/regress/lib/libcrypto/certs/verify_test.go
new file mode 100644
index 0000000000..25301109e4
--- /dev/null
+++ b/src/regress/lib/libcrypto/certs/verify_test.go
@@ -0,0 +1,111 @@
1package verify
2
3import (
4 "crypto/x509"
5 "encoding/pem"
6 "io/ioutil"
7 "path/filepath"
8 "testing"
9)
10
11func TestVerify(t *testing.T) {
12 tests := []struct {
13 id string
14 wantChains int
15 }{
16 {"1a", 1},
17 {"2a", 1},
18 {"2b", 0},
19 {"3a", 1},
20 {"3b", 0},
21 {"3c", 0},
22 {"3d", 0},
23 {"3e", 1},
24 {"4a", 2},
25 {"4b", 1},
26 {"4c", 1},
27 {"4d", 1},
28 {"4e", 1},
29 {"4f", 2},
30 {"4g", 1},
31 {"4h", 1},
32 {"5a", 2},
33 {"5b", 1},
34 {"5c", 1},
35 {"5d", 1},
36 {"5e", 1},
37 {"5f", 1},
38 {"5g", 2},
39 {"5h", 1},
40 {"5i", 1},
41 {"6a", 1}, // Expired root.
42 {"6b", 1}, // Expired root.
43 {"7a", 1}, // Expired root.
44 {"7b", 1}, // Expired root.
45 {"8a", 0}, // Expired leaf.
46 {"9a", 0}, // Expired intermediate.
47 {"10a", 1}, // Cross signed with expired intermediate.
48 {"10b", 1}, // Cross signed with expired intermediate.
49 {"11a", 1}, // Cross signed with expired intermediate.
50 {"11b", 1}, // Cross signed with expired intermediate.
51 {"12a", 1}, // Cross signed with expired intermediate.
52 {"13a", 1}, // Cross signed with expired root.
53 }
54
55 for _, test := range tests {
56 t.Run(test.id, func(t *testing.T) {
57 rootsPEM, err := ioutil.ReadFile(filepath.Join(test.id, "roots.pem"))
58 if err != nil {
59 t.Fatalf("Failed to read roots PEM: %v", err)
60 }
61 bundlePEM, err := ioutil.ReadFile(filepath.Join(test.id, "bundle.pem"))
62 if err != nil {
63 t.Fatalf("Failed to read bundle PEM: %v", err)
64 }
65
66 // Pull the leaf certificate off the top of the bundle.
67 block, intermediatesPEM := pem.Decode(bundlePEM)
68 if block == nil {
69 t.Fatal("Failed to parse leaf from bundle")
70 }
71 cert, err := x509.ParseCertificate(block.Bytes)
72 if err != nil {
73 t.Fatalf("Failed to parse certificate: %v", err)
74 }
75
76 roots := x509.NewCertPool()
77 if !roots.AppendCertsFromPEM(rootsPEM) {
78 t.Fatal("Failed to parse root certificates")
79 }
80 intermediates := x509.NewCertPool()
81 if len(intermediatesPEM) > 0 {
82 if !intermediates.AppendCertsFromPEM(intermediatesPEM) {
83 t.Fatal("Failed to parse intermediate certificates")
84 }
85 }
86
87 opts := x509.VerifyOptions{
88 Roots: roots,
89 Intermediates: intermediates,
90 }
91
92 chains, err := cert.Verify(opts)
93 if err != nil {
94 if test.wantChains > 0 {
95 t.Errorf("Failed to verify certificate: %v", err)
96 }
97 return
98 }
99 t.Logf("Found %d chains", len(chains))
100 if got, want := len(chains), test.wantChains; got != want {
101 t.Errorf("Got %d chains, want %d", got, want)
102 }
103 for i, chain := range chains {
104 t.Logf("Chain %d\n", i)
105 for _, cert := range chain {
106 t.Logf(" %v\n", cert.Subject)
107 }
108 }
109 })
110 }
111}