259 lines
6.0 KiB
Bash
Executable File
259 lines
6.0 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Copyright 2014 The Chromium Authors
|
|
# 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.
|
|
for i in B C D E F
|
|
do
|
|
openssl rand -hex -out "out/${i}-serial" 16
|
|
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 and F-by-E by way of serial number.
|
|
python crlsetutil.py -o ../certificates/multi-root-crlset-CD-and-FE.raw \
|
|
<<CRLSETDOCBLOCK
|
|
{
|
|
"BlockedByHash": {
|
|
"out/D.pem": ["out/C.pem"],
|
|
"out/E.pem": ["out/F.pem"]
|
|
}
|
|
}
|
|
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 (D, not issued by E) to enable all paths.
|
|
python crlsetutil.py -o ../certificates/multi-root-crlset-unrelated.raw \
|
|
<<CRLSETDOCBLOCK
|
|
{
|
|
"BlockedByHash": {
|
|
"out/E.pem": ["out/D.pem"]
|
|
}
|
|
}
|
|
CRLSETDOCBLOCK
|