1#!/bin/sh 2 3# Copyright 2014 The Chromium Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7# The following documentation uses the annotation approach from RFC 4158. 8# CAs (entities that share the same name and public key) are denoted in boxes, 9# while the indication that a CA Foo signed a certificate for CA Bar is denoted 10# by directed arrows. 11# 12# +---+ +-----+ 13# | D | | E | 14# +---+ +-----+ 15# | | | 16# +--v v--+ | 17# +---+ +---+ 18# | C | | F | 19# +---+ +---+ 20# | | 21# v v---+ 22# +-----+ 23# | B | 24# +-----+ 25# | 26# v 27# +---+ 28# | A | 29# +---+ 30# 31# To validate A, there are several possible paths, using A(B) to indicate 32# the certificate A signed by B: 33# 34# 1. A(B) -> B(C) -> C(D) -> D(D) 35# 3. A(B) -> B(C) -> C(E) -> E(E) 36# 4. A(B) -> B(F) -> F(E) -> E(E) 37# 38# That is, there are two different versions of C (signed by D and E) and 39# two versions of B (signed by C and F). Possible trust anchors are D and E, 40# which are both self-signed. 41# 42# The goal is to ensure that, as long as at least one of C or F is still valid, 43# clients are able to successfully build a valid path. 44 45# Exit script as soon a something fails. 46set -e 47 48rm -rf out 49mkdir out 50 51echo Create the serial and index number files. 52for i in B C D E F 53do 54 openssl rand -hex -out "out/${i}-serial" 16 55 touch "out/${i}-index.txt" 56done 57 58echo Generate the keys. 59for i in A B C D E F 60do 61 openssl genrsa -out "out/${i}.key" 2048 62done 63 64echo "Generating the self-signed roots" 65for i in D E 66do 67 echo "Generating CSR ${i}" 68 CA_COMMON_NAME="${i} Root CA - Multi-root" \ 69 CERTIFICATE="${i}" \ 70 openssl req \ 71 -config redundant-ca.cnf \ 72 -new \ 73 -key "out/${i}.key" \ 74 -out "out/${i}.csr" 75 76 echo "Generating self-signed ${i}" 77 CA_COMMON_NAME="${i} Root CA - Multi-root" \ 78 CERTIFICATE="${i}" \ 79 openssl ca \ 80 -config redundant-ca.cnf \ 81 -batch \ 82 -startdate 160102000000Z \ 83 -enddate 260102000000Z \ 84 -extensions ca_cert \ 85 -extfile redundant-ca.cnf \ 86 -selfsign \ 87 -in "out/${i}.csr" \ 88 -out "out/${i}.pem" 89done 90 91echo "Generating intermediate CSRs" 92for i in B C F 93do 94 echo "Generating CSR ${i}" 95 CA_COMMON_NAME="${i} CA - Multi-root" \ 96 CERTIFICATE="${i}" \ 97 openssl req \ 98 -config redundant-ca.cnf \ 99 -new \ 100 -key "out/${i}.key" \ 101 -out "out/${i}.csr" 102done 103 104echo D signs C 105CA_COMMON_NAME="D CA - Multi-root" \ 106CERTIFICATE=D \ 107openssl ca \ 108 -config redundant-ca.cnf \ 109 -batch \ 110 -startdate 160103000000Z \ 111 -enddate 260102000000Z \ 112 -extensions ca_cert \ 113 -extfile redundant-ca.cnf \ 114 -in out/C.csr \ 115 -out out/C.pem 116 117echo C signs B 118CA_COMMON_NAME="C CA - Multi-root" \ 119CERTIFICATE=C \ 120openssl ca \ 121 -config redundant-ca.cnf \ 122 -batch \ 123 -startdate 160104000000Z \ 124 -enddate 260102000000Z \ 125 -extensions ca_cert \ 126 -extfile redundant-ca.cnf \ 127 -in out/B.csr \ 128 -out out/B.pem 129 130echo E signs C2 131CA_COMMON_NAME="E CA - Multi-root" \ 132CERTIFICATE=E \ 133openssl ca \ 134 -config redundant-ca.cnf \ 135 -batch \ 136 -startdate 160105000000Z \ 137 -enddate 260102000000Z \ 138 -extensions ca_cert \ 139 -extfile redundant-ca.cnf \ 140 -in out/C.csr \ 141 -out out/C2.pem 142 143echo E signs F 144CA_COMMON_NAME="E CA - Multi-root" \ 145CERTIFICATE=E \ 146openssl ca \ 147 -config redundant-ca.cnf \ 148 -batch \ 149 -startdate 160102000000Z \ 150 -enddate 260102000000Z \ 151 -extensions ca_cert \ 152 -extfile redundant-ca.cnf \ 153 -in out/F.csr \ 154 -out out/F.pem 155 156# Note: The startdate for B-by-F MUST be different than that of B-by-C; to make 157# B-by-F more preferable, the startdate is chosen to be GREATER (later) than 158# B-by-C. 159echo F signs B2 160CA_COMMON_NAME="F CA - Multi-root" \ 161CERTIFICATE=F \ 162openssl ca \ 163 -config redundant-ca.cnf \ 164 -batch \ 165 -startdate 160105000000Z \ 166 -enddate 260102000000Z \ 167 -extensions ca_cert \ 168 -extfile redundant-ca.cnf \ 169 -in out/B.csr \ 170 -out out/B2.pem 171 172echo "Generating leaf CSRs" 173for i in A 174do 175 echo "Generating leaf ${i}" 176 openssl req \ 177 -config ee.cnf \ 178 -new \ 179 -key "out/${i}.key" \ 180 -out "out/${i}.csr" 181done 182 183echo "Signing leaves" 184CA_COMMON_NAME="B CA - Multi-root" \ 185CERTIFICATE=B \ 186openssl ca \ 187 -config redundant-ca.cnf \ 188 -batch \ 189 -days 3650 \ 190 -extensions user_cert \ 191 -extfile redundant-ca.cnf \ 192 -in out/A.csr \ 193 -out out/A.pem 194 195echo "Copying outputs" 196/bin/sh -c "cat out/A.key out/A.pem > ../certificates/multi-root-A-by-B.pem" 197/bin/sh -c "cat out/A.pem out/B.pem out/C.pem out/D.pem \ 198 > ../certificates/multi-root-chain1.pem" 199/bin/sh -c "cat out/A.pem out/B.pem out/C2.pem out/E.pem \ 200 > ../certificates/multi-root-chain2.pem" 201cp out/B.pem ../certificates/multi-root-B-by-C.pem 202cp out/B2.pem ../certificates/multi-root-B-by-F.pem 203cp out/C.pem ../certificates/multi-root-C-by-D.pem 204cp out/C2.pem ../certificates/multi-root-C-by-E.pem 205cp out/F.pem ../certificates/multi-root-F-by-E.pem 206cp out/D.pem ../certificates/multi-root-D-by-D.pem 207cp out/E.pem ../certificates/multi-root-E-by-E.pem 208 209echo "Generating CRLSets" 210# Block D and E by SPKI; invalidates all paths. 211python crlsetutil.py -o ../certificates/multi-root-crlset-D-and-E.raw \ 212<<CRLSETDOCBLOCK 213{ 214 "BlockedBySPKI": [ 215 "out/D.pem", 216 "out/E.pem" 217 ] 218} 219CRLSETDOCBLOCK 220 221# Block E by SPKI. 222python crlsetutil.py -o ../certificates/multi-root-crlset-E.raw \ 223<<CRLSETDOCBLOCK 224{ 225 "BlockedBySPKI": [ 226 "out/E.pem" 227 ] 228} 229CRLSETDOCBLOCK 230 231# Block C-by-D and F-by-E by way of serial number. 232python crlsetutil.py -o ../certificates/multi-root-crlset-CD-and-FE.raw \ 233<<CRLSETDOCBLOCK 234{ 235 "BlockedByHash": { 236 "out/D.pem": ["out/C.pem"], 237 "out/E.pem": ["out/F.pem"] 238 } 239} 240CRLSETDOCBLOCK 241 242# Block C (all versions) by way of SPKI 243python crlsetutil.py -o ../certificates/multi-root-crlset-C.raw \ 244<<CRLSETDOCBLOCK 245{ 246 "BlockedBySPKI": [ "out/C.pem" ] 247} 248CRLSETDOCBLOCK 249 250# Block an unrelated/unissued serial (D, not issued by E) to enable all paths. 251python crlsetutil.py -o ../certificates/multi-root-crlset-unrelated.raw \ 252<<CRLSETDOCBLOCK 253{ 254 "BlockedByHash": { 255 "out/E.pem": ["out/D.pem"] 256 } 257} 258CRLSETDOCBLOCK 259