xref: /aosp_15_r20/external/cronet/net/data/ssl/scripts/generate-multi-root-test-chains.sh (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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