12e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan/* Copyright (c) 2017, Google Inc.
22e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan *
32e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * Permission to use, copy, modify, and/or distribute this software for any
42e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * purpose with or without fee is hereby granted, provided that the above
52e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * copyright notice and this permission notice appear in all copies.
62e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan *
72e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
82e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
92e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
102e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
112e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
122e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
132e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
142e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
152e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan// make_many_constraints.go generates test certificates many_constraints.pem,
162e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan// many_names*.pem, and some_names*.pem for x509_test.cc
172e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanpackage main
182e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
192e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanimport (
202e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"crypto/rand"
212e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"crypto/rsa"
222e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"crypto/x509"
232e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"crypto/x509/pkix"
242e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"encoding/asn1"
252e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"encoding/pem"
262e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"fmt"
272e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"math/big"
282e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"os"
292e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	"time"
302e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan)
312e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
322e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanconst privateKeyPEM = `-----BEGIN PRIVATE KEY-----
332e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6C9qEGRIBQXV8
342e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanLj29vVu+U+tyXzSSinWIumK5ijPhCm3DLnv4RayxkFwemtnkGRZ/o94ZnsXkBfU/
352e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanIlsYdkuq8wK9WI/ql3gwWjH+KARIhIQcSLGiJcLN6kGuG2nlRBKMcPgPiEq2B0yB
362e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanXFf4tG3CBbeae7+8G7uvOmv8NLyKj32neWpnUCTL5o2VwyPoxjLxT5gUR69v9XSV
372e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanFj2irCZbsEedeKSb++LqyMhLfnRTzNv+ZHNh4izZHrktR25MvnT5QyBq32hx7AjZ
382e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan2/xo70OmH7w10a2DwsVjJNMdxTEmgyvU9M6CeYRPX1Ykfg+sXCTtkTVAlBDUviIq
392e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanY95CKy25AgMBAAECggEAHPvvxRiqx2tNRFVn5QF1I4erbJwMcrADc5OmAcXYIz0e
402e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloansIOzaJBiQR9+Wn5BZ9nIuYXr+g3UQpvzAyz1CDCVxUIqsRj1AtUqMk4675+IW0vZ
412e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan0RY6Jkq/uJjANsGqk78xLJQE8VaIXSdx8c1THznsx4dgfT6+Ni4T5U6yuA33OZaw
422e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan4NdYZYtEkqNiqK6VYe4mAxxVh5qscihVVMGkBVqJNiiEotctm1lph8ow+7o8ggXO
432e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanW9xm+RHHPcH7Epx7hjkb/helANcYOK950W5/R+2zWV9R6kxo6R+/hfGFFmCvl4k5
442e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan+i8Y0IlEv3fze1E0Lwyf379i3C/cKcuaE5gwR54BAQKBgQDxlsNy9M37HgguglHt
452e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan8W+cuPNtxNjFCWIjNR9dSvdr1Oi28Z1AY+BBPSv6UBKnT5PpOFjqxfMY/j/zoKdI
462e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanaYX1phgeQHXcHrB1pS8yoaF/pTJSN2Yb8v9kl/Ch1yeYXaNVGmeBLkH9H6wIcUxD
472e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanMas1i8VUzshzhcluCNGoJj9wUQKBgQDFJOoWncssfWCrsuDWEoeU71Zh3+bD96GF
482e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloans29CdIbHpcbxhWYjA9RM8yxbGPopexzoGcV1HX6j8E1s0xfYZJV23rxoM9Zj9l5D
492e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanmZAJQPxYXIdu3h4PslhZLd3p+DEHjbsLC/avk3M4iZim1FMPBJMswKSL23ysqXoY
502e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan/ynor+W06QKBgHYeu6M6NHgCYAe1ai+Hq4WaHFNgOohkJRqHv7USkVSkvb+s9LDl
512e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan5GChcx4pBmXNj8ko5rirXkerEEOjGgdaqMfJlOM9qyKb0rVCtYfw5RCPCcKPGZqy
522e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanvdJGQ74tf0uNBO34QgE0R8lmMevS0XHNGCPPGgV0MSfikvD82N15De1xAoGAbsZM
532e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanRsMJfAlDPZc4oPEuf/BwMHTYPTsy5map2MSTSzGKdQHJH1myfD6TqOiDALXtyzlX
542e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan63PUShfn2YNPvcbe+Tk00rR1/htcYk2yUpDSenAbpZ9ncth6rjmInURZgG4SMKXb
552e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanSlLnBljCjtN1jFW8wQPKMc/14SslsVAHY3ka8KkCgYB58QNT1YfH3jS62+mT2pXq
562e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert SloanqLjLqvsD742VYnFoHR+HBOnN8ry0dda4lgwM106L5FgSg9DOZvASZ+QGFk+QVQv+
572e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanc77ASWpuhmBmamZCrwZXrq9Xc92RDPkKFqnP9MVv06hYKNp0moSdM8dIaM6uSows
582e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan/r/aDs4oudubz26o5GDKmA==
592e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan-----END PRIVATE KEY-----`
602e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
612e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanvar privateKey *rsa.PrivateKey
622e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
632e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanfunc init() {
642e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	in := []byte(privateKeyPEM)
652e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	keyBlock, in := pem.Decode(in)
662e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if keyBlock == nil || keyBlock.Type != "PRIVATE KEY" {
672e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic("could not decode private key")
682e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
692e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	key, err := x509.ParsePKCS8PrivateKey(keyBlock.Bytes)
702e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
712e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
722e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
732e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	privateKey = key.(*rsa.PrivateKey)
742e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan}
752e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
762e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanfunc randOrDie(out []byte) {
772e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if _, err := rand.Reader.Read(out); err != nil {
782e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
792e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
802e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan}
812e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
822e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanfunc writePEM(path string, in []byte) {
832e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	file, err := os.Create(path)
842e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
852e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
862e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
872e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	defer file.Close()
882e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	err = pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: in})
892e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
902e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
912e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
922e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan}
932e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
942e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloanfunc main() {
952e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	notBefore, err := time.Parse(time.RFC3339, "2000-01-01T00:00:00Z")
962e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
972e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
982e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
992e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	notAfter, err := time.Parse(time.RFC3339, "2100-01-01T00:00:00Z")
1002e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
1012e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
1022e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1032e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
1042e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	caTemplate := x509.Certificate{
1052e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		SerialNumber:          new(big.Int).SetInt64(1),
1062e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		Subject:               pkix.Name{CommonName: "CA"},
1072e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		NotBefore:             notBefore,
1082e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		NotAfter:              notAfter,
1092e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		BasicConstraintsValid: true,
1102e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		IsCA:               true,
1112e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		ExtKeyUsage:        []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
1122e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		KeyUsage:           x509.KeyUsageCertSign,
1132e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		SignatureAlgorithm: x509.SHA256WithRSA,
1142e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1152e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	for i := 0; i < 513; i++ {
1162e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		caTemplate.ExcludedDNSDomains = append(caTemplate.ExcludedDNSDomains, fmt.Sprintf("x%d.test", i))
1172e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1182e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	for i := 0; i < 513; i++ {
1192e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		caTemplate.PermittedDNSDomains = append(caTemplate.PermittedDNSDomains, fmt.Sprintf("t%d.test", i))
1202e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1212e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	caTemplate.PermittedDNSDomains = append(caTemplate.PermittedDNSDomains, ".test")
1222e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	caBytes, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, &privateKey.PublicKey, privateKey)
1232e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
1242e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
1252e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1262e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	writePEM("many_constraints.pem", caBytes)
1272e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
1282e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	ca, err := x509.ParseCertificate(caBytes)
1292e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	if err != nil {
1302e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		panic(err)
1312e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1322e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
1332e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	leaves := []struct {
1342e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		path   string
1352e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		names  int
1362e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		emails int
1372e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}{
1382e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"many_names1.pem", 513, 513},
1392e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"many_names2.pem", 1025, 0},
1402e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"many_names3.pem", 0, 1025},
1412e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"some_names1.pem", 256, 256},
1422e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"some_names2.pem", 513, 0},
1432e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		{"some_names3.pem", 0, 513},
1442e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1452e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	for i, leaf := range leaves {
1462e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		leafTemplate := x509.Certificate{
1472e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			SerialNumber:          new(big.Int).SetInt64(int64(i + 2)),
1482e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			Subject:               pkix.Name{CommonName: "t0.test"},
1492e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			NotBefore:             notBefore,
1502e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			NotAfter:              notAfter,
1512e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			BasicConstraintsValid: true,
1522e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			IsCA:               false,
1532e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			ExtKeyUsage:        []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
1542e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			KeyUsage:           x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
1552e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			SignatureAlgorithm: x509.SHA256WithRSA,
1562e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		}
1572e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		for i := 0; i < leaf.names; i++ {
1582e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			leafTemplate.DNSNames = append(leafTemplate.DNSNames, fmt.Sprintf("t%d.test", i))
1592e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		}
1602e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		for i := 0; i < leaf.emails; i++ {
1612e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			leafTemplate.Subject.ExtraNames = append(leafTemplate.Subject.ExtraNames, pkix.AttributeTypeAndValue{
1622e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan				Type: []int{1, 2, 840, 113549, 1, 9, 1},
1632e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan				Value: asn1.RawValue{
1642e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan					Class:      asn1.ClassUniversal,
1652e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan					Tag:        asn1.TagIA5String,
1662e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan					IsCompound: false,
1672e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan					Bytes:      []byte(fmt.Sprintf("t%d@test", i)),
1682e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan				},
1692e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			})
1702e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		}
1712e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		leafBytes, err := x509.CreateCertificate(rand.Reader, &leafTemplate, ca, &privateKey.PublicKey, privateKey)
1722e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		if err != nil {
1732e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan			panic(err)
1742e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		}
1752e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan
1762e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan		writePEM(leaf.path, leafBytes)
1772e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan	}
1782e9e66ad8f35ee615e79da22ff91b0fa94607ca8Robert Sloan}
179