• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2020, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15//go:build ignore
16
17// make_policy_certs.go generates certificates for testing policy handling.
18package main
19
20import (
21	"crypto/ecdsa"
22	"crypto/rand"
23	"crypto/x509"
24	"crypto/x509/pkix"
25	"encoding/asn1"
26	"encoding/pem"
27	"flag"
28	"math/big"
29	"os"
30	"time"
31
32	"golang.org/x/crypto/cryptobyte"
33	cbasn1 "golang.org/x/crypto/cryptobyte/asn1"
34)
35
36var resetFlag = flag.Bool("reset", false, "if set, regenerates certificates that already exist")
37
38var (
39	// https://davidben.net/oid
40	testOID1 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 1})
41	testOID2 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 2})
42	testOID3 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 3})
43	testOID4 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 4})
44	testOID5 = asn1.ObjectIdentifier([]int{1, 2, 840, 113554, 4, 1, 72585, 2, 5})
45
46	// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.4
47	certificatePoliciesOID = asn1.ObjectIdentifier([]int{2, 5, 29, 32})
48	anyPolicyOID           = asn1.ObjectIdentifier([]int{2, 5, 29, 32, 0})
49
50	// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.5
51	policyMappingsOID = asn1.ObjectIdentifier([]int{2, 5, 29, 33})
52
53	// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.2.1.11
54	policyConstraintsOID = asn1.ObjectIdentifier([]int{2, 5, 29, 36})
55)
56
57var leafKey, intermediateKey, rootKey *ecdsa.PrivateKey
58
59func init() {
60	leafKey = mustParseECDSAKey(leafKeyPEM)
61	intermediateKey = mustParseECDSAKey(intermediateKeyPEM)
62	rootKey = mustParseECDSAKey(rootKeyPEM)
63}
64
65type templateAndKey struct {
66	template x509.Certificate
67	key      *ecdsa.PrivateKey
68}
69
70func mustGenerateCertificate(path string, subject, issuer *templateAndKey) {
71	if !*resetFlag {
72		// Skip if the file already exists.
73		_, err := os.Stat(path)
74		if err == nil {
75			return
76		}
77		if !os.IsNotExist(err) {
78			panic(err)
79		}
80	}
81	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
82	if err != nil {
83		panic(err)
84	}
85	file, err := os.Create(path)
86	if err != nil {
87		panic(err)
88	}
89	defer file.Close()
90	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
91	if err != nil {
92		panic(err)
93	}
94}
95
96func main() {
97	flag.Parse()
98
99	notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
100	if err != nil {
101		panic(err)
102	}
103	notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z")
104	if err != nil {
105		panic(err)
106	}
107
108	root2 := templateAndKey{
109		template: x509.Certificate{
110			SerialNumber:          new(big.Int).SetInt64(1),
111			Subject:               pkix.Name{CommonName: "Policy Root 2"},
112			NotBefore:             notBefore,
113			NotAfter:              notAfter,
114			BasicConstraintsValid: true,
115			IsCA:                  true,
116			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
117			KeyUsage:              x509.KeyUsageCertSign,
118			SignatureAlgorithm:    x509.ECDSAWithSHA256,
119		},
120		key: rootKey,
121	}
122	root := templateAndKey{
123		template: x509.Certificate{
124			SerialNumber:          new(big.Int).SetInt64(1),
125			Subject:               pkix.Name{CommonName: "Policy Root"},
126			NotBefore:             notBefore,
127			NotAfter:              notAfter,
128			BasicConstraintsValid: true,
129			IsCA:                  true,
130			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
131			KeyUsage:              x509.KeyUsageCertSign,
132			SignatureAlgorithm:    x509.ECDSAWithSHA256,
133		},
134		key: rootKey,
135	}
136	intermediate := templateAndKey{
137		template: x509.Certificate{
138			SerialNumber:          new(big.Int).SetInt64(2),
139			Subject:               pkix.Name{CommonName: "Policy Intermediate"},
140			NotBefore:             notBefore,
141			NotAfter:              notAfter,
142			BasicConstraintsValid: true,
143			IsCA:                  true,
144			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
145			KeyUsage:              x509.KeyUsageCertSign,
146			SignatureAlgorithm:    x509.ECDSAWithSHA256,
147			PolicyIdentifiers:     []asn1.ObjectIdentifier{testOID1, testOID2},
148		},
149		key: intermediateKey,
150	}
151	leaf := templateAndKey{
152		template: x509.Certificate{
153			SerialNumber:          new(big.Int).SetInt64(3),
154			Subject:               pkix.Name{CommonName: "www.example.com"},
155			NotBefore:             notBefore,
156			NotAfter:              notAfter,
157			BasicConstraintsValid: true,
158			IsCA:                  false,
159			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
160			KeyUsage:              x509.KeyUsageCertSign,
161			SignatureAlgorithm:    x509.ECDSAWithSHA256,
162			DNSNames:              []string{"www.example.com"},
163			PolicyIdentifiers:     []asn1.ObjectIdentifier{testOID1, testOID2},
164		},
165		key: leafKey,
166	}
167
168	// Generate a valid certificate chain from the templates.
169	mustGenerateCertificate("policy_root.pem", &root, &root)
170	mustGenerateCertificate("policy_intermediate.pem", &intermediate, &root)
171	mustGenerateCertificate("policy_leaf.pem", &leaf, &intermediate)
172
173	// root2 is used for tests that need a longer chain, using a Root/Root2
174	// cross-sign as one of the certificates.
175	mustGenerateCertificate("policy_root2.pem", &root2, &root2)
176
177	// Introduce syntax errors in the leaf and intermediate.
178	leafInvalid := leaf
179	leafInvalid.template.PolicyIdentifiers = nil
180	leafInvalid.template.ExtraExtensions = []pkix.Extension{{Id: certificatePoliciesOID, Value: []byte("INVALID")}}
181	mustGenerateCertificate("policy_leaf_invalid.pem", &leafInvalid, &root)
182
183	intermediateInvalid := intermediate
184	intermediateInvalid.template.PolicyIdentifiers = nil
185	intermediateInvalid.template.ExtraExtensions = []pkix.Extension{{Id: certificatePoliciesOID, Value: []byte("INVALID")}}
186	mustGenerateCertificate("policy_intermediate_invalid.pem", &intermediateInvalid, &root)
187
188	// Duplicates are not allowed in certificatePolicies.
189	leafDuplicate := leaf
190	leafDuplicate.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID1, testOID2, testOID2}
191	mustGenerateCertificate("policy_leaf_duplicate.pem", &leafDuplicate, &root)
192
193	intermediateDuplicate := intermediate
194	intermediateDuplicate.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID1, testOID2, testOID2}
195	mustGenerateCertificate("policy_intermediate_duplicate.pem", &intermediateDuplicate, &root)
196
197	// Various policy constraints with requireExplicitPolicy values.
198	b := cryptobyte.NewBuilder(nil)
199	b.AddASN1(cbasn1.SEQUENCE, func(seq *cryptobyte.Builder) {
200		seq.AddASN1Int64WithTag(0, cbasn1.Tag(0).ContextSpecific())
201	})
202	requireExplicitPolicy0 := b.BytesOrPanic()
203
204	b = cryptobyte.NewBuilder(nil)
205	b.AddASN1(cbasn1.SEQUENCE, func(seq *cryptobyte.Builder) {
206		seq.AddASN1Int64WithTag(1, cbasn1.Tag(0).ContextSpecific())
207	})
208	requireExplicitPolicy1 := b.BytesOrPanic()
209
210	b = cryptobyte.NewBuilder(nil)
211	b.AddASN1(cbasn1.SEQUENCE, func(seq *cryptobyte.Builder) {
212		seq.AddASN1Int64WithTag(2, cbasn1.Tag(0).ContextSpecific())
213	})
214	requireExplicitPolicy2 := b.BytesOrPanic()
215
216	// A version of the intermediate that sets requireExplicitPolicy, skipping
217	// zero certificates.
218	intermediateRequire := intermediate
219	intermediateRequire.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: requireExplicitPolicy0}}
220	mustGenerateCertificate("policy_intermediate_require.pem", &intermediateRequire, &root)
221
222	// Same as above, but there are no policies on the intermediate.
223	intermediateRequire.template.PolicyIdentifiers = nil
224	mustGenerateCertificate("policy_intermediate_require_no_policies.pem", &intermediateRequire, &root)
225
226	// Same as above, but the policy list has duplicates.
227	intermediateRequire.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID1, testOID2, testOID2}
228	mustGenerateCertificate("policy_intermediate_require_duplicate.pem", &intermediateRequire, &root)
229
230	// Corresponding certificates that instead assert the anyPolicy OID.
231	intermediateAny := intermediate
232	intermediateAny.template.PolicyIdentifiers = []asn1.ObjectIdentifier{anyPolicyOID}
233	mustGenerateCertificate("policy_intermediate_any.pem", &intermediateAny, &root)
234
235	// Other requireExplicitPolicy values, on the leaf and intermediate.
236	intermediateRequire = intermediate
237	intermediateRequire.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: requireExplicitPolicy1}}
238	mustGenerateCertificate("policy_intermediate_require1.pem", &intermediateRequire, &root)
239	intermediateRequire.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: requireExplicitPolicy2}}
240	mustGenerateCertificate("policy_intermediate_require2.pem", &intermediateRequire, &root)
241	leafRequire := leaf
242	leafRequire.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: requireExplicitPolicy0}}
243	mustGenerateCertificate("policy_leaf_require.pem", &leafRequire, &intermediate)
244	leafRequire.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: requireExplicitPolicy1}}
245	mustGenerateCertificate("policy_leaf_require1.pem", &leafRequire, &intermediate)
246
247	leafAny := leaf
248	leafAny.template.PolicyIdentifiers = []asn1.ObjectIdentifier{anyPolicyOID}
249	mustGenerateCertificate("policy_leaf_any.pem", &leafAny, &intermediate)
250
251	// An intermediate which maps OID1 to (OID2, OID3), and which asserts the
252	// input OIDs either all at once, or as anyPolicy.
253	b = cryptobyte.NewBuilder(nil)
254	b.AddASN1(cbasn1.SEQUENCE, func(seq *cryptobyte.Builder) {
255		// Map OID3 to (OID1, OID2).
256		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
257			mapping.AddASN1ObjectIdentifier(testOID3)
258			mapping.AddASN1ObjectIdentifier(testOID1)
259		})
260		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
261			mapping.AddASN1ObjectIdentifier(testOID3)
262			mapping.AddASN1ObjectIdentifier(testOID2)
263		})
264
265		// Map all pairs of OID4 and OID5 to each other.
266		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
267			mapping.AddASN1ObjectIdentifier(testOID4)
268			mapping.AddASN1ObjectIdentifier(testOID4)
269		})
270		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
271			mapping.AddASN1ObjectIdentifier(testOID4)
272			mapping.AddASN1ObjectIdentifier(testOID5)
273		})
274		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
275			mapping.AddASN1ObjectIdentifier(testOID5)
276			mapping.AddASN1ObjectIdentifier(testOID4)
277		})
278		seq.AddASN1(cbasn1.SEQUENCE, func(mapping *cryptobyte.Builder) {
279			mapping.AddASN1ObjectIdentifier(testOID5)
280			mapping.AddASN1ObjectIdentifier(testOID5)
281		})
282	})
283	intermediateMapped := intermediate
284	intermediateMapped.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID1, testOID2, testOID3, testOID4, testOID5}
285	intermediateMapped.template.ExtraExtensions = []pkix.Extension{{Id: policyMappingsOID, Value: b.BytesOrPanic()}}
286	mustGenerateCertificate("policy_intermediate_mapped.pem", &intermediateMapped, &root)
287
288	intermediateMapped.template.PolicyIdentifiers = []asn1.ObjectIdentifier{anyPolicyOID}
289	mustGenerateCertificate("policy_intermediate_mapped_any.pem", &intermediateMapped, &root)
290
291	intermediateMapped.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID3}
292	mustGenerateCertificate("policy_intermediate_mapped_oid3.pem", &intermediateMapped, &root)
293
294	// Leaves which assert more specific OIDs, to test intermediate_mapped.
295	leafSingle := leaf
296	leafSingle.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID1}
297	mustGenerateCertificate("policy_leaf_oid1.pem", &leafSingle, &intermediate)
298	leafSingle.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID2}
299	mustGenerateCertificate("policy_leaf_oid2.pem", &leafSingle, &intermediate)
300	leafSingle.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID3}
301	mustGenerateCertificate("policy_leaf_oid3.pem", &leafSingle, &intermediate)
302	leafSingle.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID4}
303	mustGenerateCertificate("policy_leaf_oid4.pem", &leafSingle, &intermediate)
304	leafSingle.template.PolicyIdentifiers = []asn1.ObjectIdentifier{testOID5}
305	mustGenerateCertificate("policy_leaf_oid5.pem", &leafSingle, &intermediate)
306
307	leafNone := leaf
308	leafNone.template.PolicyIdentifiers = nil
309	mustGenerateCertificate("policy_leaf_none.pem", &leafNone, &intermediate)
310
311	// Make version of Root, signed by Root 2, with policy mapping inhibited.
312	// This can be combined with intermediateMapped to test the combination.
313	b = cryptobyte.NewBuilder(nil)
314	b.AddASN1(cbasn1.SEQUENCE, func(seq *cryptobyte.Builder) {
315		seq.AddASN1Int64WithTag(0, cbasn1.Tag(1).ContextSpecific())
316	})
317	inhibitPolicyMapping0 := b.BytesOrPanic()
318
319	inhibitMapping := root
320	inhibitMapping.template.PolicyIdentifiers = []asn1.ObjectIdentifier{anyPolicyOID}
321	inhibitMapping.template.ExtraExtensions = []pkix.Extension{{Id: policyConstraintsOID, Value: inhibitPolicyMapping0}}
322	mustGenerateCertificate("policy_root_cross_inhibit_mapping.pem", &inhibitMapping, &root2)
323}
324
325const leafKeyPEM = `-----BEGIN PRIVATE KEY-----
326MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoPUXNXuH9mgiS/nk
327024SYxryxMa3CyGJldiHymLxSquhRANCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5
328w8u3SSwm7HZREvmcBCJBjVIREacRqI0umhzR2V5NLzBBP9yPD/A+Ch5X
329-----END PRIVATE KEY-----`
330
331const intermediateKeyPEM = `-----BEGIN PRIVATE KEY-----
332MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWHKCKgY058ahE3t6
333vpxVQgzlycgCVMogwjK0y3XMNfWhRANCAATiOnyojN4xS5C8gJ/PHL5cOEsMbsoE
334Y6KT9xRQSh8lEL4d1Vb36kqUgkpqedEImo0Og4Owk6VWVVR/m4Lk+yUw
335-----END PRIVATE KEY-----`
336
337const rootKeyPEM = `-----BEGIN PRIVATE KEY-----
338MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBwND/eHytW0I417J
339Hr+qcPlp5N1jM3ACXys57bPujg+hRANCAAQmdqXYl1GvY7y3jcTTK6MVXIQr44Tq
340ChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAPEPSJwPndjolt
341-----END PRIVATE KEY-----`
342
343func mustParseECDSAKey(in string) *ecdsa.PrivateKey {
344	keyBlock, _ := pem.Decode([]byte(in))
345	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
346		panic("could not decode private key")
347	}
348	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
349	if err != nil {
350		panic(err)
351	}
352	return key.(*ecdsa.PrivateKey)
353}
354