#!/bin/sh # Copyright 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # The following documentation uses the annotation approach from RFC 4158. # CAs (entities that share the same name and public key) are denoted in boxes, # while the indication that a CA Foo signed a certificate for CA Bar is denoted # by directed arrows. # # +---+ +-----+ # | D | | E | # +---+ +-----+ # | | | # +--v v--+ | # +---+ +---+ # | C | | F | # +---+ +---+ # | | # v v---+ # +-----+ # | B | # +-----+ # | # v # +---+ # | A | # +---+ # # To validate A, there are several possible paths, using A(B) to indicate # the certificate A signed by B: # # 1. A(B) -> B(C) -> C(D) -> D(D) # 3. A(B) -> B(C) -> C(E) -> E(E) # 4. A(B) -> B(F) -> F(E) -> E(E) # # That is, there are two different versions of C (signed by D and E) and # two versions of B (signed by C and F). Possible trust anchors are D and E, # which are both self-signed. # # The goal is to ensure that, as long as at least one of C or F is still valid, # clients are able to successfully build a valid path. # Exit script as soon a something fails. set -e rm -rf out mkdir out echo Create the serial and index number files. serial=1000 for i in B C D E F do /bin/sh -c "echo ${serial} > out/${i}-serial" touch "out/${i}-index.txt" done echo Generate the keys. for i in A B C D E F do openssl genrsa -out "out/${i}.key" 2048 done echo "Generating the self-signed roots" for i in D E do echo "Generating CSR ${i}" CA_COMMON_NAME="${i} Root CA - Multi-root" \ CERTIFICATE="${i}" \ openssl req \ -config redundant-ca.cnf \ -new \ -key "out/${i}.key" \ -out "out/${i}.csr" echo "Generating self-signed ${i}" CA_COMMON_NAME="${i} Root CA - Multi-root" \ CERTIFICATE="${i}" \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160102000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -selfsign \ -in "out/${i}.csr" \ -out "out/${i}.pem" done echo "Generating intermediate CSRs" for i in B C F do echo "Generating CSR ${i}" CA_COMMON_NAME="${i} CA - Multi-root" \ CERTIFICATE="${i}" \ openssl req \ -config redundant-ca.cnf \ -new \ -key "out/${i}.key" \ -out "out/${i}.csr" done echo D signs C CA_COMMON_NAME="D CA - Multi-root" \ CERTIFICATE=D \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160103000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -in out/C.csr \ -out out/C.pem echo C signs B CA_COMMON_NAME="C CA - Multi-root" \ CERTIFICATE=C \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160104000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -in out/B.csr \ -out out/B.pem echo E signs C2 CA_COMMON_NAME="E CA - Multi-root" \ CERTIFICATE=E \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160105000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -in out/C.csr \ -out out/C2.pem echo E signs F CA_COMMON_NAME="E CA - Multi-root" \ CERTIFICATE=E \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160102000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -in out/F.csr \ -out out/F.pem # Note: The startdate for B-by-F MUST be different than that of B-by-C; to make # B-by-F more preferable, the startdate is chosen to be GREATER (later) than # B-by-C. echo F signs B2 CA_COMMON_NAME="F CA - Multi-root" \ CERTIFICATE=F \ openssl ca \ -config redundant-ca.cnf \ -batch \ -startdate 160105000000Z \ -enddate 260102000000Z \ -extensions ca_cert \ -extfile redundant-ca.cnf \ -in out/B.csr \ -out out/B2.pem echo "Generating leaf CSRs" for i in A do echo "Generating leaf ${i}" openssl req \ -config ee.cnf \ -new \ -key "out/${i}.key" \ -out "out/${i}.csr" done echo "Signing leaves" CA_COMMON_NAME="B CA - Multi-root" \ CERTIFICATE=B \ openssl ca \ -config redundant-ca.cnf \ -batch \ -days 3650 \ -extensions user_cert \ -extfile redundant-ca.cnf \ -in out/A.csr \ -out out/A.pem echo "Copying outputs" /bin/sh -c "cat out/A.key out/A.pem > ../certificates/multi-root-A-by-B.pem" /bin/sh -c "cat out/A.pem out/B.pem out/C.pem out/D.pem \ > ../certificates/multi-root-chain1.pem" /bin/sh -c "cat out/A.pem out/B.pem out/C2.pem out/E.pem \ > ../certificates/multi-root-chain2.pem" cp out/B.pem ../certificates/multi-root-B-by-C.pem cp out/B2.pem ../certificates/multi-root-B-by-F.pem cp out/C.pem ../certificates/multi-root-C-by-D.pem cp out/C2.pem ../certificates/multi-root-C-by-E.pem cp out/F.pem ../certificates/multi-root-F-by-E.pem cp out/D.pem ../certificates/multi-root-D-by-D.pem cp out/E.pem ../certificates/multi-root-E-by-E.pem echo "Generating CRLSets" # Block D and E by SPKI; invalidates all paths. python crlsetutil.py -o ../certificates/multi-root-crlset-D-and-E.raw \ <<CRLSETDOCBLOCK { "BlockedBySPKI": [ "out/D.pem", "out/E.pem" ] } CRLSETDOCBLOCK # Block E by SPKI. python crlsetutil.py -o ../certificates/multi-root-crlset-E.raw \ <<CRLSETDOCBLOCK { "BlockedBySPKI": [ "out/E.pem" ] } CRLSETDOCBLOCK # Block C-by-D (serial number 0x1001) and F-by-E (serial number 0x1002) by # way of serial number. python crlsetutil.py -o ../certificates/multi-root-crlset-CD-and-FE.raw \ <<CRLSETDOCBLOCK { "BlockedByHash": { "out/D.pem": [4097], "out/E.pem": [4098] } } CRLSETDOCBLOCK # Block C (all versions) by way of SPKI python crlsetutil.py -o ../certificates/multi-root-crlset-C.raw \ <<CRLSETDOCBLOCK { "BlockedBySPKI": [ "out/C.pem" ] } CRLSETDOCBLOCK # Block an unrelated/unissued serial (0x0FFF) to enable all paths. python crlsetutil.py -o ../certificates/multi-root-crlset-unrelated.raw \ <<CRLSETDOCBLOCK { "BlockedByHash": { "out/E.pem": [4095] } } CRLSETDOCBLOCK