diff options
author | jsing <> | 2020-07-14 18:27:28 +0000 |
---|---|---|
committer | jsing <> | 2020-07-14 18:27:28 +0000 |
commit | f133c373915d3c0ab63b4365469c5023561f3443 (patch) | |
tree | 8adad7e0ea025db74f93d91fc64fd242671ca862 /src/regress/lib/libcrypto | |
parent | 02b2b8724bbd999e01f85ef375fb6611f378d302 (diff) | |
download | openbsd-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/Makefile | 21 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/certs/README | 123 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/certs/make-certs.sh | 381 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/certs/verify_test.go | 111 |
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)) | ||
4 | GO_VERSION != sh -c "(go version) 2>/dev/null || true" | ||
5 | .endif | ||
6 | |||
7 | .if empty(GO_VERSION) | ||
8 | regress: | ||
9 | @echo package go is required for this regress | ||
10 | @echo SKIPPED | ||
11 | .endif | ||
12 | |||
13 | REGRESS_TARGETS=regress-go-verify | ||
14 | |||
15 | certs: | ||
16 | cd ${.CURDIR} && sh ./make-certs.sh | ||
17 | |||
18 | regress-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 @@ | |||
1 | This directory contains tools for building certificate chains to | ||
2 | test verification. Each subdirectory contains a set of certificates | ||
3 | that test a particular scenario. The root certificate(s) are contained | ||
4 | in a roots.pem file, while the leaf certificate and any untrusted | ||
5 | intermediate 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 | |||
103 | 10a. 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 | |||
107 | 10b. Same as (10a) but order of intermediates is reversed (should verify | ||
108 | with one chain. | ||
109 | |||
110 | 11a. 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 | |||
114 | 11b. Same as (11a) but order of intermediates is reversed (should verify | ||
115 | with one chain. | ||
116 | |||
117 | 12a. 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 | |||
121 | 13a. 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 | |||
19 | set -e | ||
20 | set -u | ||
21 | set -x | ||
22 | |||
23 | readonly SUBJECT="/CN=LibreSSL Test" | ||
24 | |||
25 | readonly TMPDIR=$(mktemp -d) | ||
26 | |||
27 | cleanup() { | ||
28 | rm -rf "${TMPDIR}" | ||
29 | } | ||
30 | |||
31 | trap cleanup EXIT INT | ||
32 | |||
33 | reset() { | ||
34 | echo '100001' > ${TMPDIR}/certserial | ||
35 | cat /dev/null > ${TMPDIR}/certindex | ||
36 | } | ||
37 | |||
38 | setup() { | ||
39 | reset | ||
40 | |||
41 | cat > ${TMPDIR}/openssl.cnf <<EOF | ||
42 | [ca] | ||
43 | default_ca = test_ca | ||
44 | |||
45 | [test_ca] | ||
46 | new_certs_dir = ${TMPDIR}/ | ||
47 | database = ${TMPDIR}/certindex | ||
48 | default_days = 365 | ||
49 | default_md = sha256 | ||
50 | policy = test_policy | ||
51 | serial = ${TMPDIR}/certserial | ||
52 | |||
53 | [test_policy] | ||
54 | countryName = optional | ||
55 | stateOrProvinceName = optional | ||
56 | localityName = optional | ||
57 | organizationName = optional | ||
58 | organizationalUnitName = optional | ||
59 | commonName = supplied | ||
60 | emailAddress = optional | ||
61 | |||
62 | [v3_ca_root] | ||
63 | subjectKeyIdentifier = hash | ||
64 | authorityKeyIdentifier = keyid:always,issuer | ||
65 | basicConstraints = critical, CA:true | ||
66 | keyUsage = critical, cRLSign, keyCertSign | ||
67 | |||
68 | [v3_ca_int] | ||
69 | subjectKeyIdentifier = hash | ||
70 | authorityKeyIdentifier = keyid:always,issuer | ||
71 | basicConstraints = critical, CA:true | ||
72 | keyUsage = critical, cRLSign, keyCertSign | ||
73 | |||
74 | [v3_other] | ||
75 | subjectKeyIdentifier = hash | ||
76 | authorityKeyIdentifier = keyid:always,issuer | ||
77 | basicConstraints = critical, CA:false | ||
78 | keyUsage = critical, digitalSignature | ||
79 | |||
80 | [req] | ||
81 | distinguished_name = req_distinguished_name | ||
82 | |||
83 | [ req_distinguished_name ] | ||
84 | EOF | ||
85 | } | ||
86 | |||
87 | create_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 | |||
96 | create_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 | |||
110 | create_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 | |||
122 | create_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 | |||
135 | create_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 | |||
147 | create_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 | |||
160 | create_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 | |||
169 | create_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 | |||
179 | create_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 | |||
195 | create_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 | |||
208 | setup | ||
209 | |||
210 | # Scenario 1a. | ||
211 | reset | ||
212 | create_root "Root CA 1" "ca-root" | ||
213 | create_leaf "Server 1" "server-1" "ca-root" | ||
214 | create_root_bundle "./1a/roots.pem" "ca-root" | ||
215 | create_bundle "./1a/bundle.pem" "server-1" | ||
216 | |||
217 | # Scenarios 2a and 2b. | ||
218 | reset | ||
219 | create_root "Root CA 1" "ca-root" | ||
220 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" | ||
221 | create_leaf "Server 1" "server-1" "ca-int-1" | ||
222 | create_root_bundle "./2a/roots.pem" "ca-root" | ||
223 | create_bundle "./2a/bundle.pem" "server-1" "ca-int-1" | ||
224 | create_root_bundle "./2b/roots.pem" "ca-root" | ||
225 | create_bundle "./2b/bundle.pem" "server-1" | ||
226 | |||
227 | # Scenarios 3a, 3b, 3c, 3d and 3e. | ||
228 | reset | ||
229 | create_root "Root CA 1" "ca-root" | ||
230 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" | ||
231 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
232 | create_intermediate "Intermediate CA 3" "ca-int-3" "ca-int-2" | ||
233 | create_leaf "Server 1" "server-1" "ca-int-3" | ||
234 | create_root_bundle "./3a/roots.pem" "ca-root" | ||
235 | create_bundle "./3a/bundle.pem" "server-1" "ca-int-3" "ca-int-2" "ca-int-1" | ||
236 | create_root_bundle "./3b/roots.pem" "ca-root" | ||
237 | create_bundle "./3b/bundle.pem" "server-1" "ca-int-3" "ca-int-2" | ||
238 | create_root_bundle "./3c/roots.pem" "ca-root" | ||
239 | create_bundle "./3c/bundle.pem" "server-1" "ca-int-3" "ca-int-1" | ||
240 | create_root_bundle "./3d/roots.pem" "ca-root" | ||
241 | create_bundle "./3d/bundle.pem" "server-1" "ca-int-2" "ca-int-1" | ||
242 | create_root_bundle "./3e/roots.pem" "ca-root" | ||
243 | create_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. | ||
246 | reset | ||
247 | create_root "Root CA 1" "ca-root-1" | ||
248 | create_root "Root CA 2" "ca-root-2" | ||
249 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
250 | create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2" | ||
251 | create_leaf "Server 1" "server-1" "ca-int-1" | ||
252 | create_root_bundle "./4a/roots.pem" "ca-root-1" "ca-root-2" | ||
253 | create_bundle "./4a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" | ||
254 | create_root_bundle "./4b/roots.pem" "ca-root-1" | ||
255 | create_bundle "./4b/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" | ||
256 | create_root_bundle "./4c/roots.pem" "ca-root-2" | ||
257 | create_bundle "./4c/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" | ||
258 | create_root_bundle "./4d/roots.pem" "ca-root-1" "ca-root-2" | ||
259 | create_bundle "./4d/bundle.pem" "server-1" "ca-int-1" | ||
260 | create_root_bundle "./4e/roots.pem" "ca-root-1" "ca-root-2" | ||
261 | create_bundle "./4e/bundle.pem" "server-1" "ca-int-1-xs" | ||
262 | create_root_bundle "./4f/roots.pem" "ca-root-1" "ca-root-2" | ||
263 | create_bundle "./4f/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" | ||
264 | create_root_bundle "./4g/roots.pem" "ca-root-1" | ||
265 | create_bundle "./4g/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" | ||
266 | create_root_bundle "./4h/roots.pem" "ca-root-2" | ||
267 | create_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. | ||
270 | reset | ||
271 | create_root "Root CA 1" "ca-root-1" | ||
272 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
273 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
274 | create_root "Root CA 2" "ca-root-2" | ||
275 | create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" | ||
276 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
277 | create_root_bundle "./5a/roots.pem" "ca-root-1" "ca-root-2" | ||
278 | create_bundle "./5a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
279 | create_root_bundle "./5b/roots.pem" "ca-root-2" | ||
280 | create_bundle "./5b/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
281 | create_root_bundle "./5c/roots.pem" "ca-root-1" | ||
282 | create_bundle "./5c/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
283 | create_root_bundle "./5d/roots.pem" "ca-root-1" "ca-root-2" | ||
284 | create_bundle "./5d/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-1" | ||
285 | create_root_bundle "./5e/roots.pem" "ca-root-1" "ca-root-2" | ||
286 | create_bundle "./5e/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" | ||
287 | create_root_bundle "./5f/roots.pem" "ca-root-1" "ca-root-2" | ||
288 | create_bundle "./5f/bundle.pem" "server-1" "ca-int-2" "ca-int-1" | ||
289 | create_root_bundle "./5g/roots.pem" "ca-root-1" "ca-root-2" | ||
290 | create_bundle "./5g/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
291 | create_root_bundle "./5h/roots.pem" "ca-root-2" | ||
292 | create_bundle "./5h/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
293 | create_root_bundle "./5i/roots.pem" "ca-root-1" | ||
294 | create_bundle "./5i/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
295 | |||
296 | # Scenarios 6a and 6b. | ||
297 | reset | ||
298 | create_root "Root CA 1" "ca-root-1" | ||
299 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
300 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
301 | create_expired_root "Root CA 2" "ca-root-2" | ||
302 | create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" | ||
303 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
304 | create_root_bundle "./6a/roots.pem" "ca-root-1" "ca-root-2" | ||
305 | create_bundle "./6a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
306 | create_root_bundle "./6b/roots.pem" "ca-root-1" "ca-root-2" | ||
307 | create_bundle "./6b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
308 | |||
309 | # Scenarios 7a and 7b. | ||
310 | reset | ||
311 | create_expired_root "Root CA 1" "ca-root-1" | ||
312 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
313 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
314 | create_root "Root CA 2" "ca-root-2" | ||
315 | create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" | ||
316 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
317 | create_root_bundle "./7a/roots.pem" "ca-root-1" "ca-root-2" | ||
318 | create_bundle "./7a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
319 | create_root_bundle "./7b/roots.pem" "ca-root-1" "ca-root-2" | ||
320 | create_bundle "./7b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
321 | |||
322 | # Scenario 8a. | ||
323 | reset | ||
324 | create_root "Root CA 1" "ca-root" | ||
325 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" | ||
326 | create_expired_leaf "Server 1" "server-1" "ca-int-1" | ||
327 | create_root_bundle "./8a/roots.pem" "ca-root" | ||
328 | create_bundle "./8a/bundle.pem" "server-1" "ca-int-1" | ||
329 | |||
330 | # Scenario 9a. | ||
331 | reset | ||
332 | create_root "Root CA 1" "ca-root" | ||
333 | create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" | ||
334 | create_leaf "Server 1" "server-1" "ca-int-1" | ||
335 | create_root_bundle "./9a/roots.pem" "ca-root" | ||
336 | create_bundle "./9a/bundle.pem" "server-1" "ca-int-1" | ||
337 | |||
338 | # Scenarios 10a and 10b. | ||
339 | reset | ||
340 | create_root "Root CA 1" "ca-root-1" | ||
341 | create_root "Root CA 2" "ca-root-2" | ||
342 | create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
343 | create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2" | ||
344 | create_leaf "Server 1" "server-1" "ca-int-1" | ||
345 | create_root_bundle "./10a/roots.pem" "ca-root-1" "ca-root-2" | ||
346 | create_bundle "./10a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" | ||
347 | create_root_bundle "./10b/roots.pem" "ca-root-1" "ca-root-2" | ||
348 | create_bundle "./10b/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" | ||
349 | |||
350 | # Scenarios 11a and 11b. | ||
351 | reset | ||
352 | create_root "Root CA 1" "ca-root-1" | ||
353 | create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
354 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
355 | create_root "Root CA 2" "ca-root-2" | ||
356 | create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" | ||
357 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
358 | create_root_bundle "./11a/roots.pem" "ca-root-1" "ca-root-2" | ||
359 | create_bundle "./11a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" | ||
360 | create_root_bundle "./11b/roots.pem" "ca-root-1" "ca-root-2" | ||
361 | create_bundle "./11b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" | ||
362 | |||
363 | # Scenario 12a. | ||
364 | reset | ||
365 | create_root "Root CA 1" "ca-root-1" | ||
366 | create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
367 | create_cross_signed "ca-root-2" "ca-int-1" "ca-root-1" | ||
368 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
369 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
370 | create_root_bundle "./12a/roots.pem" "ca-root-1" "ca-root-2" | ||
371 | create_bundle "./12a/bundle.pem" "server-1" "ca-int-2" "ca-int-1" | ||
372 | |||
373 | # Scenario 13a. | ||
374 | reset | ||
375 | create_root "Root CA 1" "ca-root-1" | ||
376 | create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" | ||
377 | create_expired_cross_signed "ca-root-2" "ca-int-1" "ca-root-1" | ||
378 | create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" | ||
379 | create_leaf "Server 1" "server-1" "ca-int-2" | ||
380 | create_root_bundle "./13a/roots.pem" "ca-root-1" "ca-root-2" | ||
381 | create_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 @@ | |||
1 | package verify | ||
2 | |||
3 | import ( | ||
4 | "crypto/x509" | ||
5 | "encoding/pem" | ||
6 | "io/ioutil" | ||
7 | "path/filepath" | ||
8 | "testing" | ||
9 | ) | ||
10 | |||
11 | func 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 | } | ||