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" 226create_root_bundle "./2c/roots.pem" "ca-root" 227create_bundle "./2c/bundle.pem" "server-1" "ca-root" "ca-int-1" 228 229# Scenarios 3a, 3b, 3c, 3d and 3e. 230reset 231create_root "Root CA 1" "ca-root" 232create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" 233create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 234create_intermediate "Intermediate CA 3" "ca-int-3" "ca-int-2" 235create_leaf "Server 1" "server-1" "ca-int-3" 236create_root_bundle "./3a/roots.pem" "ca-root" 237create_bundle "./3a/bundle.pem" "server-1" "ca-int-3" "ca-int-2" "ca-int-1" 238create_root_bundle "./3b/roots.pem" "ca-root" 239create_bundle "./3b/bundle.pem" "server-1" "ca-int-3" "ca-int-2" 240create_root_bundle "./3c/roots.pem" "ca-root" 241create_bundle "./3c/bundle.pem" "server-1" "ca-int-3" "ca-int-1" 242create_root_bundle "./3d/roots.pem" "ca-root" 243create_bundle "./3d/bundle.pem" "server-1" "ca-int-2" "ca-int-1" 244create_root_bundle "./3e/roots.pem" "ca-root" 245create_bundle "./3e/bundle.pem" "server-1" "ca-int-1" "ca-int-2" "ca-int-3" 246 247# Scenarios 4a, 4b, 4c, 4d, 4e, 4f, 4g and 4h. 248reset 249create_root "Root CA 1" "ca-root-1" 250create_root "Root CA 2" "ca-root-2" 251create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 252create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2" 253create_leaf "Server 1" "server-1" "ca-int-1" 254create_root_bundle "./4a/roots.pem" "ca-root-1" "ca-root-2" 255create_bundle "./4a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" 256create_root_bundle "./4b/roots.pem" "ca-root-1" 257create_bundle "./4b/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" 258create_root_bundle "./4c/roots.pem" "ca-root-2" 259create_bundle "./4c/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" 260create_root_bundle "./4d/roots.pem" "ca-root-1" "ca-root-2" 261create_bundle "./4d/bundle.pem" "server-1" "ca-int-1" 262create_root_bundle "./4e/roots.pem" "ca-root-1" "ca-root-2" 263create_bundle "./4e/bundle.pem" "server-1" "ca-int-1-xs" 264create_root_bundle "./4f/roots.pem" "ca-root-1" "ca-root-2" 265create_bundle "./4f/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" 266create_root_bundle "./4g/roots.pem" "ca-root-1" 267create_bundle "./4g/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" 268create_root_bundle "./4h/roots.pem" "ca-root-2" 269create_bundle "./4h/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" 270 271# Scenario 5a, 5b, 5c, 5d, 5e, 5f, 5g, 5h and 5i. 272reset 273create_root "Root CA 1" "ca-root-1" 274create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 275create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 276create_root "Root CA 2" "ca-root-2" 277create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" 278create_leaf "Server 1" "server-1" "ca-int-2" 279create_root_bundle "./5a/roots.pem" "ca-root-1" "ca-root-2" 280create_bundle "./5a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 281create_root_bundle "./5b/roots.pem" "ca-root-2" 282create_bundle "./5b/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 283create_root_bundle "./5c/roots.pem" "ca-root-1" 284create_bundle "./5c/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 285create_root_bundle "./5d/roots.pem" "ca-root-1" "ca-root-2" 286create_bundle "./5d/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-1" 287create_root_bundle "./5e/roots.pem" "ca-root-1" "ca-root-2" 288create_bundle "./5e/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" 289create_root_bundle "./5f/roots.pem" "ca-root-1" "ca-root-2" 290create_bundle "./5f/bundle.pem" "server-1" "ca-int-2" "ca-int-1" 291create_root_bundle "./5g/roots.pem" "ca-root-1" "ca-root-2" 292create_bundle "./5g/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 293create_root_bundle "./5h/roots.pem" "ca-root-2" 294create_bundle "./5h/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 295create_root_bundle "./5i/roots.pem" "ca-root-1" 296create_bundle "./5i/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 297 298# Scenarios 6a and 6b. 299reset 300create_root "Root CA 1" "ca-root-1" 301create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 302create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 303create_expired_root "Root CA 2" "ca-root-2" 304create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" 305create_leaf "Server 1" "server-1" "ca-int-2" 306create_root_bundle "./6a/roots.pem" "ca-root-1" "ca-root-2" 307create_bundle "./6a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 308create_root_bundle "./6b/roots.pem" "ca-root-1" "ca-root-2" 309create_bundle "./6b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 310 311# Scenarios 7a and 7b. 312reset 313create_expired_root "Root CA 1" "ca-root-1" 314create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 315create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 316create_root "Root CA 2" "ca-root-2" 317create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" 318create_leaf "Server 1" "server-1" "ca-int-2" 319create_root_bundle "./7a/roots.pem" "ca-root-1" "ca-root-2" 320create_bundle "./7a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 321create_root_bundle "./7b/roots.pem" "ca-root-1" "ca-root-2" 322create_bundle "./7b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 323 324# Scenario 8a. 325reset 326create_root "Root CA 1" "ca-root" 327create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" 328create_expired_leaf "Server 1" "server-1" "ca-int-1" 329create_root_bundle "./8a/roots.pem" "ca-root" 330create_bundle "./8a/bundle.pem" "server-1" "ca-int-1" 331 332# Scenario 9a. 333reset 334create_root "Root CA 1" "ca-root" 335create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root" 336create_leaf "Server 1" "server-1" "ca-int-1" 337create_root_bundle "./9a/roots.pem" "ca-root" 338create_bundle "./9a/bundle.pem" "server-1" "ca-int-1" 339 340# Scenarios 10a and 10b. 341reset 342create_root "Root CA 1" "ca-root-1" 343create_root "Root CA 2" "ca-root-2" 344create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 345create_cross_signed "ca-int-1-xs" "ca-int-1" "ca-root-2" 346create_leaf "Server 1" "server-1" "ca-int-1" 347create_root_bundle "./10a/roots.pem" "ca-root-1" "ca-root-2" 348create_bundle "./10a/bundle.pem" "server-1" "ca-int-1" "ca-int-1-xs" 349create_root_bundle "./10b/roots.pem" "ca-root-1" "ca-root-2" 350create_bundle "./10b/bundle.pem" "server-1" "ca-int-1-xs" "ca-int-1" 351 352# Scenarios 11a and 11b. 353reset 354create_root "Root CA 1" "ca-root-1" 355create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 356create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 357create_root "Root CA 2" "ca-root-2" 358create_cross_signed "ca-int-2-xs" "ca-int-2" "ca-root-2" 359create_leaf "Server 1" "server-1" "ca-int-2" 360create_root_bundle "./11a/roots.pem" "ca-root-1" "ca-root-2" 361create_bundle "./11a/bundle.pem" "server-1" "ca-int-2" "ca-int-2-xs" "ca-int-1" 362create_root_bundle "./11b/roots.pem" "ca-root-1" "ca-root-2" 363create_bundle "./11b/bundle.pem" "server-1" "ca-int-2-xs" "ca-int-2" "ca-int-1" 364 365# Scenario 12a. 366reset 367create_root "Root CA 1" "ca-root-1" 368create_expired_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 369create_cross_signed "ca-root-2" "ca-int-1" "ca-root-1" 370create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 371create_leaf "Server 1" "server-1" "ca-int-2" 372create_root_bundle "./12a/roots.pem" "ca-root-1" "ca-root-2" 373create_bundle "./12a/bundle.pem" "server-1" "ca-int-2" "ca-int-1" 374 375# Scenario 13a. 376reset 377create_root "Root CA 1" "ca-root-1" 378create_intermediate "Intermediate CA 1" "ca-int-1" "ca-root-1" 379create_expired_cross_signed "ca-root-2" "ca-int-1" "ca-root-1" 380create_intermediate "Intermediate CA 2" "ca-int-2" "ca-int-1" 381create_leaf "Server 1" "server-1" "ca-int-2" 382create_root_bundle "./13a/roots.pem" "ca-root-1" "ca-root-2" 383create_bundle "./13a/bundle.pem" "server-1" "ca-int-2" "ca-int-1" 384