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