1// Package certutil contains helper functions that are mostly used
2// with the PKI backend but can be generally useful. Functionality
3// includes helpers for converting a certificate/private key bundle
4// between DER and PEM, printing certificate serial numbers, and more.
5//
6// Functionality specific to the PKI backend includes some types
7// and helper methods to make requesting certificates from the
8// backend easy.
9package certutil
10
11import (
12	"bytes"
13	"crypto"
14	"crypto/ecdsa"
15	"crypto/rsa"
16	"crypto/tls"
17	"crypto/x509"
18	"crypto/x509/pkix"
19	"encoding/pem"
20	"fmt"
21	"math/big"
22	"net"
23	"net/url"
24	"strings"
25	"time"
26
27	"github.com/hashicorp/errwrap"
28	"github.com/hashicorp/vault/sdk/helper/errutil"
29)
30
31const (
32	PrivateKeyTypeP521 = "p521"
33)
34
35// This can be one of a few key types so the different params may or may not be filled
36type ClusterKeyParams struct {
37	Type string   `json:"type" structs:"type" mapstructure:"type"`
38	X    *big.Int `json:"x" structs:"x" mapstructure:"x"`
39	Y    *big.Int `json:"y" structs:"y" mapstructure:"y"`
40	D    *big.Int `json:"d" structs:"d" mapstructure:"d"`
41}
42
43// Secret is used to attempt to unmarshal a Vault secret
44// JSON response, as a convenience
45type Secret struct {
46	Data map[string]interface{} `json:"data"`
47}
48
49// PrivateKeyType holds a string representation of the type of private key (ec
50// or rsa) referenced in CertBundle and ParsedCertBundle. This uses colloquial
51// names rather than official names, to eliminate confusion
52type PrivateKeyType string
53
54// Well-known PrivateKeyTypes
55const (
56	UnknownPrivateKey PrivateKeyType = ""
57	RSAPrivateKey     PrivateKeyType = "rsa"
58	ECPrivateKey      PrivateKeyType = "ec"
59)
60
61// TLSUsage controls whether the intended usage of a *tls.Config
62// returned from ParsedCertBundle.getTLSConfig is for server use,
63// client use, or both, which affects which values are set
64type TLSUsage int
65
66// Well-known TLSUsage types
67const (
68	TLSUnknown TLSUsage = 0
69	TLSServer  TLSUsage = 1 << iota
70	TLSClient
71)
72
73// BlockType indicates the serialization format of the key
74type BlockType string
75
76// Well-known formats
77const (
78	PKCS1Block BlockType = "RSA PRIVATE KEY"
79	PKCS8Block BlockType = "PRIVATE KEY"
80	ECBlock    BlockType = "EC PRIVATE KEY"
81)
82
83// ParsedPrivateKeyContainer allows common key setting for certs and CSRs
84type ParsedPrivateKeyContainer interface {
85	SetParsedPrivateKey(crypto.Signer, PrivateKeyType, []byte)
86}
87
88// CertBlock contains the DER-encoded certificate and the PEM
89// block's byte array
90type CertBlock struct {
91	Certificate *x509.Certificate
92	Bytes       []byte
93}
94
95// CertBundle contains a key type, a PEM-encoded private key,
96// a PEM-encoded certificate, and a string-encoded serial number,
97// returned from a successful Issue request
98type CertBundle struct {
99	PrivateKeyType PrivateKeyType `json:"private_key_type" structs:"private_key_type" mapstructure:"private_key_type"`
100	Certificate    string         `json:"certificate" structs:"certificate" mapstructure:"certificate"`
101	IssuingCA      string         `json:"issuing_ca" structs:"issuing_ca" mapstructure:"issuing_ca"`
102	CAChain        []string       `json:"ca_chain" structs:"ca_chain" mapstructure:"ca_chain"`
103	PrivateKey     string         `json:"private_key" structs:"private_key" mapstructure:"private_key"`
104	SerialNumber   string         `json:"serial_number" structs:"serial_number" mapstructure:"serial_number"`
105}
106
107// ParsedCertBundle contains a key type, a DER-encoded private key,
108// and a DER-encoded certificate
109type ParsedCertBundle struct {
110	PrivateKeyType   PrivateKeyType
111	PrivateKeyFormat BlockType
112	PrivateKeyBytes  []byte
113	PrivateKey       crypto.Signer
114	CertificateBytes []byte
115	Certificate      *x509.Certificate
116	CAChain          []*CertBlock
117}
118
119// CSRBundle contains a key type, a PEM-encoded private key,
120// and a PEM-encoded CSR
121type CSRBundle struct {
122	PrivateKeyType PrivateKeyType `json:"private_key_type" structs:"private_key_type" mapstructure:"private_key_type"`
123	CSR            string         `json:"csr" structs:"csr" mapstructure:"csr"`
124	PrivateKey     string         `json:"private_key" structs:"private_key" mapstructure:"private_key"`
125}
126
127// ParsedCSRBundle contains a key type, a DER-encoded private key,
128// and a DER-encoded certificate request
129type ParsedCSRBundle struct {
130	PrivateKeyType  PrivateKeyType
131	PrivateKeyBytes []byte
132	PrivateKey      crypto.Signer
133	CSRBytes        []byte
134	CSR             *x509.CertificateRequest
135}
136
137// ToPEMBundle converts a string-based certificate bundle
138// to a PEM-based string certificate bundle in trust path
139// order, leaf certificate first
140func (c *CertBundle) ToPEMBundle() string {
141	var result []string
142
143	if len(c.PrivateKey) > 0 {
144		result = append(result, c.PrivateKey)
145	}
146	if len(c.Certificate) > 0 {
147		result = append(result, c.Certificate)
148	}
149	if len(c.CAChain) > 0 {
150		result = append(result, c.CAChain...)
151	}
152
153	return strings.Join(result, "\n")
154}
155
156// ToParsedCertBundle converts a string-based certificate bundle
157// to a byte-based raw certificate bundle
158func (c *CertBundle) ToParsedCertBundle() (*ParsedCertBundle, error) {
159	result := &ParsedCertBundle{}
160	var err error
161	var pemBlock *pem.Block
162
163	if len(c.PrivateKey) > 0 {
164		pemBlock, _ = pem.Decode([]byte(c.PrivateKey))
165		if pemBlock == nil {
166			return nil, errutil.UserError{Err: "Error decoding private key from cert bundle"}
167		}
168
169		result.PrivateKeyBytes = pemBlock.Bytes
170		result.PrivateKeyFormat = BlockType(strings.TrimSpace(pemBlock.Type))
171
172		switch result.PrivateKeyFormat {
173		case ECBlock:
174			result.PrivateKeyType, c.PrivateKeyType = ECPrivateKey, ECPrivateKey
175		case PKCS1Block:
176			c.PrivateKeyType, result.PrivateKeyType = RSAPrivateKey, RSAPrivateKey
177		case PKCS8Block:
178			t, err := getPKCS8Type(pemBlock.Bytes)
179			if err != nil {
180				return nil, errutil.UserError{Err: fmt.Sprintf("Error getting key type from pkcs#8: %v", err)}
181			}
182			result.PrivateKeyType = t
183			switch t {
184			case ECPrivateKey:
185				c.PrivateKeyType = ECPrivateKey
186			case RSAPrivateKey:
187				c.PrivateKeyType = RSAPrivateKey
188			}
189		default:
190			return nil, errutil.UserError{Err: fmt.Sprintf("Unsupported key block type: %s", pemBlock.Type)}
191		}
192
193		result.PrivateKey, err = result.getSigner()
194		if err != nil {
195			return nil, errutil.UserError{Err: fmt.Sprintf("Error getting signer: %s", err)}
196		}
197	}
198
199	if len(c.Certificate) > 0 {
200		pemBlock, _ = pem.Decode([]byte(c.Certificate))
201		if pemBlock == nil {
202			return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
203		}
204		result.CertificateBytes = pemBlock.Bytes
205		result.Certificate, err = x509.ParseCertificate(result.CertificateBytes)
206		if err != nil {
207			return nil, errutil.UserError{Err: fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle: %v", err)}
208		}
209	}
210	switch {
211	case len(c.CAChain) > 0:
212		for _, cert := range c.CAChain {
213			pemBlock, _ := pem.Decode([]byte(cert))
214			if pemBlock == nil {
215				return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
216			}
217
218			parsedCert, err := x509.ParseCertificate(pemBlock.Bytes)
219			if err != nil {
220				return nil, errutil.UserError{Err: fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle via CA chain: %v", err)}
221			}
222
223			certBlock := &CertBlock{
224				Bytes:       pemBlock.Bytes,
225				Certificate: parsedCert,
226			}
227			result.CAChain = append(result.CAChain, certBlock)
228		}
229
230	// For backwards compatibility
231	case len(c.IssuingCA) > 0:
232		pemBlock, _ = pem.Decode([]byte(c.IssuingCA))
233		if pemBlock == nil {
234			return nil, errutil.UserError{Err: "Error decoding ca certificate from cert bundle"}
235		}
236
237		parsedCert, err := x509.ParseCertificate(pemBlock.Bytes)
238		if err != nil {
239			return nil, errutil.UserError{Err: fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle via issuing CA: %v", err)}
240		}
241
242		certBlock := &CertBlock{
243			Bytes:       pemBlock.Bytes,
244			Certificate: parsedCert,
245		}
246		result.CAChain = append(result.CAChain, certBlock)
247	}
248
249	// Populate if it isn't there already
250	if len(c.SerialNumber) == 0 && len(c.Certificate) > 0 {
251		c.SerialNumber = GetHexFormatted(result.Certificate.SerialNumber.Bytes(), ":")
252	}
253
254	return result, nil
255}
256
257// ToCertBundle converts a byte-based raw DER certificate bundle
258// to a PEM-based string certificate bundle
259func (p *ParsedCertBundle) ToCertBundle() (*CertBundle, error) {
260	result := &CertBundle{}
261	block := pem.Block{
262		Type: "CERTIFICATE",
263	}
264
265	if p.Certificate != nil {
266		result.SerialNumber = strings.TrimSpace(GetHexFormatted(p.Certificate.SerialNumber.Bytes(), ":"))
267	}
268
269	if p.CertificateBytes != nil && len(p.CertificateBytes) > 0 {
270		block.Bytes = p.CertificateBytes
271		result.Certificate = strings.TrimSpace(string(pem.EncodeToMemory(&block)))
272	}
273
274	for _, caCert := range p.CAChain {
275		block.Bytes = caCert.Bytes
276		certificate := strings.TrimSpace(string(pem.EncodeToMemory(&block)))
277
278		result.CAChain = append(result.CAChain, certificate)
279	}
280
281	if p.PrivateKeyBytes != nil && len(p.PrivateKeyBytes) > 0 {
282		block.Type = string(p.PrivateKeyFormat)
283		block.Bytes = p.PrivateKeyBytes
284		result.PrivateKeyType = p.PrivateKeyType
285
286		// Handle bundle not parsed by us
287		if block.Type == "" {
288			switch p.PrivateKeyType {
289			case ECPrivateKey:
290				block.Type = string(ECBlock)
291			case RSAPrivateKey:
292				block.Type = string(PKCS1Block)
293			}
294		}
295
296		result.PrivateKey = strings.TrimSpace(string(pem.EncodeToMemory(&block)))
297	}
298
299	return result, nil
300}
301
302// Verify checks if the parsed bundle is valid.  It validates the public
303// key of the certificate to the private key and checks the certificate trust
304// chain for path issues.
305func (p *ParsedCertBundle) Verify() error {
306	// If private key exists, check if it matches the public key of cert
307	if p.PrivateKey != nil && p.Certificate != nil {
308		equal, err := ComparePublicKeys(p.Certificate.PublicKey, p.PrivateKey.Public())
309		if err != nil {
310			return errwrap.Wrapf("could not compare public and private keys: {{err}}", err)
311		}
312		if !equal {
313			return fmt.Errorf("public key of certificate does not match private key")
314		}
315	}
316
317	certPath := p.GetCertificatePath()
318	if len(certPath) > 1 {
319		for i, caCert := range certPath[1:] {
320			if !caCert.Certificate.IsCA {
321				return fmt.Errorf("certificate %d of certificate chain is not a certificate authority", i+1)
322			}
323			if !bytes.Equal(certPath[i].Certificate.AuthorityKeyId, caCert.Certificate.SubjectKeyId) {
324				return fmt.Errorf("certificate %d of certificate chain ca trust path is incorrect (%q/%q) (%X/%X)",
325					i+1,
326					certPath[i].Certificate.Subject.CommonName, caCert.Certificate.Subject.CommonName,
327					certPath[i].Certificate.AuthorityKeyId, caCert.Certificate.SubjectKeyId)
328			}
329		}
330	}
331
332	return nil
333}
334
335// GetCertificatePath returns a slice of certificates making up a path, pulled
336// from the parsed cert bundle
337func (p *ParsedCertBundle) GetCertificatePath() []*CertBlock {
338	var certPath []*CertBlock
339
340	certPath = append(certPath, &CertBlock{
341		Certificate: p.Certificate,
342		Bytes:       p.CertificateBytes,
343	})
344
345	if len(p.CAChain) > 0 {
346		// Root CA puts itself in the chain
347		if p.CAChain[0].Certificate.SerialNumber != p.Certificate.SerialNumber {
348			certPath = append(certPath, p.CAChain...)
349		}
350	}
351
352	return certPath
353}
354
355// GetSigner returns a crypto.Signer corresponding to the private key
356// contained in this ParsedCertBundle. The Signer contains a Public() function
357// for getting the corresponding public. The Signer can also be
358// type-converted to private keys
359func (p *ParsedCertBundle) getSigner() (crypto.Signer, error) {
360	var signer crypto.Signer
361	var err error
362
363	if p.PrivateKeyBytes == nil || len(p.PrivateKeyBytes) == 0 {
364		return nil, errutil.UserError{Err: "Given parsed cert bundle does not have private key information"}
365	}
366
367	switch p.PrivateKeyFormat {
368	case ECBlock:
369		signer, err = x509.ParseECPrivateKey(p.PrivateKeyBytes)
370		if err != nil {
371			return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
372		}
373
374	case PKCS1Block:
375		signer, err = x509.ParsePKCS1PrivateKey(p.PrivateKeyBytes)
376		if err != nil {
377			return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
378		}
379
380	case PKCS8Block:
381		if k, err := x509.ParsePKCS8PrivateKey(p.PrivateKeyBytes); err == nil {
382			switch k := k.(type) {
383			case *rsa.PrivateKey, *ecdsa.PrivateKey:
384				return k.(crypto.Signer), nil
385			default:
386				return nil, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
387			}
388		}
389		return nil, errutil.UserError{Err: fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
390	default:
391		return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA and EC are supported"}
392	}
393	return signer, nil
394}
395
396// SetParsedPrivateKey sets the private key parameters on the bundle
397func (p *ParsedCertBundle) SetParsedPrivateKey(privateKey crypto.Signer, privateKeyType PrivateKeyType, privateKeyBytes []byte) {
398	p.PrivateKey = privateKey
399	p.PrivateKeyType = privateKeyType
400	p.PrivateKeyBytes = privateKeyBytes
401}
402
403func getPKCS8Type(bs []byte) (PrivateKeyType, error) {
404	k, err := x509.ParsePKCS8PrivateKey(bs)
405	if err != nil {
406		return UnknownPrivateKey, errutil.UserError{Err: fmt.Sprintf("Failed to parse pkcs#8 key: %v", err)}
407	}
408
409	switch k.(type) {
410	case *ecdsa.PrivateKey:
411		return ECPrivateKey, nil
412	case *rsa.PrivateKey:
413		return RSAPrivateKey, nil
414	default:
415		return UnknownPrivateKey, errutil.UserError{Err: "Found unknown private key type in pkcs#8 wrapping"}
416	}
417}
418
419// ToParsedCSRBundle converts a string-based CSR bundle
420// to a byte-based raw CSR bundle
421func (c *CSRBundle) ToParsedCSRBundle() (*ParsedCSRBundle, error) {
422	result := &ParsedCSRBundle{}
423	var err error
424	var pemBlock *pem.Block
425
426	if len(c.PrivateKey) > 0 {
427		pemBlock, _ = pem.Decode([]byte(c.PrivateKey))
428		if pemBlock == nil {
429			return nil, errutil.UserError{Err: "Error decoding private key from cert bundle"}
430		}
431		result.PrivateKeyBytes = pemBlock.Bytes
432
433		switch BlockType(pemBlock.Type) {
434		case ECBlock:
435			result.PrivateKeyType = ECPrivateKey
436		case PKCS1Block:
437			result.PrivateKeyType = RSAPrivateKey
438		default:
439			// Try to figure it out and correct
440			if _, err := x509.ParseECPrivateKey(pemBlock.Bytes); err == nil {
441				result.PrivateKeyType = ECPrivateKey
442				c.PrivateKeyType = "ec"
443			} else if _, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil {
444				result.PrivateKeyType = RSAPrivateKey
445				c.PrivateKeyType = "rsa"
446			} else {
447				return nil, errutil.UserError{Err: fmt.Sprintf("Unknown private key type in bundle: %s", c.PrivateKeyType)}
448			}
449		}
450
451		result.PrivateKey, err = result.getSigner()
452		if err != nil {
453			return nil, errutil.UserError{Err: fmt.Sprintf("Error getting signer: %s", err)}
454		}
455	}
456
457	if len(c.CSR) > 0 {
458		pemBlock, _ = pem.Decode([]byte(c.CSR))
459		if pemBlock == nil {
460			return nil, errutil.UserError{Err: "Error decoding certificate from cert bundle"}
461		}
462		result.CSRBytes = pemBlock.Bytes
463		result.CSR, err = x509.ParseCertificateRequest(result.CSRBytes)
464		if err != nil {
465			return nil, errutil.UserError{Err: fmt.Sprintf("Error encountered parsing certificate bytes from raw bundle via CSR: %v", err)}
466		}
467	}
468
469	return result, nil
470}
471
472// ToCSRBundle converts a byte-based raw DER certificate bundle
473// to a PEM-based string certificate bundle
474func (p *ParsedCSRBundle) ToCSRBundle() (*CSRBundle, error) {
475	result := &CSRBundle{}
476	block := pem.Block{
477		Type: "CERTIFICATE REQUEST",
478	}
479
480	if p.CSRBytes != nil && len(p.CSRBytes) > 0 {
481		block.Bytes = p.CSRBytes
482		result.CSR = strings.TrimSpace(string(pem.EncodeToMemory(&block)))
483	}
484
485	if p.PrivateKeyBytes != nil && len(p.PrivateKeyBytes) > 0 {
486		block.Bytes = p.PrivateKeyBytes
487		switch p.PrivateKeyType {
488		case RSAPrivateKey:
489			result.PrivateKeyType = "rsa"
490			block.Type = "RSA PRIVATE KEY"
491		case ECPrivateKey:
492			result.PrivateKeyType = "ec"
493			block.Type = "EC PRIVATE KEY"
494		default:
495			return nil, errutil.InternalError{Err: "Could not determine private key type when creating block"}
496		}
497		result.PrivateKey = strings.TrimSpace(string(pem.EncodeToMemory(&block)))
498	}
499
500	return result, nil
501}
502
503// GetSigner returns a crypto.Signer corresponding to the private key
504// contained in this ParsedCSRBundle. The Signer contains a Public() function
505// for getting the corresponding public. The Signer can also be
506// type-converted to private keys
507func (p *ParsedCSRBundle) getSigner() (crypto.Signer, error) {
508	var signer crypto.Signer
509	var err error
510
511	if p.PrivateKeyBytes == nil || len(p.PrivateKeyBytes) == 0 {
512		return nil, errutil.UserError{Err: "Given parsed cert bundle does not have private key information"}
513	}
514
515	switch p.PrivateKeyType {
516	case ECPrivateKey:
517		signer, err = x509.ParseECPrivateKey(p.PrivateKeyBytes)
518		if err != nil {
519			return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private EC key: %s", err)}
520		}
521
522	case RSAPrivateKey:
523		signer, err = x509.ParsePKCS1PrivateKey(p.PrivateKeyBytes)
524		if err != nil {
525			return nil, errutil.UserError{Err: fmt.Sprintf("Unable to parse CA's private RSA key: %s", err)}
526		}
527
528	default:
529		return nil, errutil.UserError{Err: "Unable to determine type of private key; only RSA and EC are supported"}
530	}
531	return signer, nil
532}
533
534// SetParsedPrivateKey sets the private key parameters on the bundle
535func (p *ParsedCSRBundle) SetParsedPrivateKey(privateKey crypto.Signer, privateKeyType PrivateKeyType, privateKeyBytes []byte) {
536	p.PrivateKey = privateKey
537	p.PrivateKeyType = privateKeyType
538	p.PrivateKeyBytes = privateKeyBytes
539}
540
541// getTLSConfig returns a TLS config generally suitable for client
542// authentication. The returned TLS config can be modified slightly
543// to be made suitable for a server requiring client authentication;
544// specifically, you should set the value of ClientAuth in the returned
545// config to match your needs.
546func (p *ParsedCertBundle) GetTLSConfig(usage TLSUsage) (*tls.Config, error) {
547	tlsCert := tls.Certificate{
548		Certificate: [][]byte{},
549	}
550
551	tlsConfig := &tls.Config{
552		MinVersion: tls.VersionTLS12,
553	}
554
555	if p.Certificate != nil {
556		tlsCert.Leaf = p.Certificate
557	}
558
559	if p.PrivateKey != nil {
560		tlsCert.PrivateKey = p.PrivateKey
561	}
562
563	if p.CertificateBytes != nil && len(p.CertificateBytes) > 0 {
564		tlsCert.Certificate = append(tlsCert.Certificate, p.CertificateBytes)
565	}
566
567	if len(p.CAChain) > 0 {
568		for _, cert := range p.CAChain {
569			tlsCert.Certificate = append(tlsCert.Certificate, cert.Bytes)
570		}
571
572		// Technically we only need one cert, but this doesn't duplicate code
573		certBundle, err := p.ToCertBundle()
574		if err != nil {
575			return nil, errwrap.Wrapf("error converting parsed bundle to string bundle when getting TLS config: {{err}}", err)
576		}
577
578		caPool := x509.NewCertPool()
579		ok := caPool.AppendCertsFromPEM([]byte(certBundle.CAChain[0]))
580		if !ok {
581			return nil, fmt.Errorf("could not append CA certificate")
582		}
583
584		if usage&TLSServer > 0 {
585			tlsConfig.ClientCAs = caPool
586			tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
587		}
588		if usage&TLSClient > 0 {
589			tlsConfig.RootCAs = caPool
590		}
591	}
592
593	if tlsCert.Certificate != nil && len(tlsCert.Certificate) > 0 {
594		tlsConfig.Certificates = []tls.Certificate{tlsCert}
595		tlsConfig.BuildNameToCertificate()
596	}
597
598	return tlsConfig, nil
599}
600
601// IssueData is a structure that is suitable for marshaling into a request;
602// either via JSON, or into a map[string]interface{} via the structs package
603type IssueData struct {
604	TTL        string `json:"ttl" structs:"ttl" mapstructure:"ttl"`
605	CommonName string `json:"common_name" structs:"common_name" mapstructure:"common_name"`
606	OU         string `json:"ou" structs:"ou" mapstructure:"ou"`
607	AltNames   string `json:"alt_names" structs:"alt_names" mapstructure:"alt_names"`
608	IPSANs     string `json:"ip_sans" structs:"ip_sans" mapstructure:"ip_sans"`
609	CSR        string `json:"csr" structs:"csr" mapstructure:"csr"`
610	OtherSANs  string `json:"other_sans" structs:"other_sans" mapstructure:"other_sans"`
611}
612
613type URLEntries struct {
614	IssuingCertificates   []string `json:"issuing_certificates" structs:"issuing_certificates" mapstructure:"issuing_certificates"`
615	CRLDistributionPoints []string `json:"crl_distribution_points" structs:"crl_distribution_points" mapstructure:"crl_distribution_points"`
616	OCSPServers           []string `json:"ocsp_servers" structs:"ocsp_servers" mapstructure:"ocsp_servers"`
617}
618
619type CAInfoBundle struct {
620	ParsedCertBundle
621	URLs *URLEntries
622}
623
624func (b *CAInfoBundle) GetCAChain() []*CertBlock {
625	chain := []*CertBlock{}
626
627	// Include issuing CA in Chain, not including Root Authority
628	if (len(b.Certificate.AuthorityKeyId) > 0 &&
629		!bytes.Equal(b.Certificate.AuthorityKeyId, b.Certificate.SubjectKeyId)) ||
630		(len(b.Certificate.AuthorityKeyId) == 0 &&
631			!bytes.Equal(b.Certificate.RawIssuer, b.Certificate.RawSubject)) {
632
633		chain = append(chain, &CertBlock{
634			Certificate: b.Certificate,
635			Bytes:       b.CertificateBytes,
636		})
637		if b.CAChain != nil && len(b.CAChain) > 0 {
638			chain = append(chain, b.CAChain...)
639		}
640	}
641
642	return chain
643}
644
645type CertExtKeyUsage int
646
647const (
648	AnyExtKeyUsage CertExtKeyUsage = 1 << iota
649	ServerAuthExtKeyUsage
650	ClientAuthExtKeyUsage
651	CodeSigningExtKeyUsage
652	EmailProtectionExtKeyUsage
653	IpsecEndSystemExtKeyUsage
654	IpsecTunnelExtKeyUsage
655	IpsecUserExtKeyUsage
656	TimeStampingExtKeyUsage
657	OcspSigningExtKeyUsage
658	MicrosoftServerGatedCryptoExtKeyUsage
659	NetscapeServerGatedCryptoExtKeyUsage
660	MicrosoftCommercialCodeSigningExtKeyUsage
661	MicrosoftKernelCodeSigningExtKeyUsage
662)
663
664type CreationParameters struct {
665	Subject                       pkix.Name
666	DNSNames                      []string
667	EmailAddresses                []string
668	IPAddresses                   []net.IP
669	URIs                          []*url.URL
670	OtherSANs                     map[string][]string
671	IsCA                          bool
672	KeyType                       string
673	KeyBits                       int
674	NotAfter                      time.Time
675	KeyUsage                      x509.KeyUsage
676	ExtKeyUsage                   CertExtKeyUsage
677	ExtKeyUsageOIDs               []string
678	PolicyIdentifiers             []string
679	BasicConstraintsValidForNonCA bool
680
681	// Only used when signing a CA cert
682	UseCSRValues        bool
683	PermittedDNSDomains []string
684
685	// URLs to encode into the certificate
686	URLs *URLEntries
687
688	// The maximum path length to encode
689	MaxPathLength int
690
691	// The duration the certificate will use NotBefore
692	NotBeforeDuration time.Duration
693}
694
695type CreationBundle struct {
696	Params        *CreationParameters
697	SigningBundle *CAInfoBundle
698	CSR           *x509.CertificateRequest
699}
700
701// addKeyUsages adds appropriate key usages to the template given the creation
702// information
703func AddKeyUsages(data *CreationBundle, certTemplate *x509.Certificate) {
704	if data.Params.IsCA {
705		certTemplate.KeyUsage = x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign)
706		return
707	}
708
709	certTemplate.KeyUsage = data.Params.KeyUsage
710
711	if data.Params.ExtKeyUsage&AnyExtKeyUsage != 0 {
712		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageAny)
713	}
714
715	if data.Params.ExtKeyUsage&ServerAuthExtKeyUsage != 0 {
716		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
717	}
718
719	if data.Params.ExtKeyUsage&ClientAuthExtKeyUsage != 0 {
720		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
721	}
722
723	if data.Params.ExtKeyUsage&CodeSigningExtKeyUsage != 0 {
724		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning)
725	}
726
727	if data.Params.ExtKeyUsage&EmailProtectionExtKeyUsage != 0 {
728		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection)
729	}
730
731	if data.Params.ExtKeyUsage&IpsecEndSystemExtKeyUsage != 0 {
732		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECEndSystem)
733	}
734
735	if data.Params.ExtKeyUsage&IpsecTunnelExtKeyUsage != 0 {
736		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECTunnel)
737	}
738
739	if data.Params.ExtKeyUsage&IpsecUserExtKeyUsage != 0 {
740		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageIPSECUser)
741	}
742
743	if data.Params.ExtKeyUsage&TimeStampingExtKeyUsage != 0 {
744		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageTimeStamping)
745	}
746
747	if data.Params.ExtKeyUsage&OcspSigningExtKeyUsage != 0 {
748		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning)
749	}
750
751	if data.Params.ExtKeyUsage&MicrosoftServerGatedCryptoExtKeyUsage != 0 {
752		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftServerGatedCrypto)
753	}
754
755	if data.Params.ExtKeyUsage&NetscapeServerGatedCryptoExtKeyUsage != 0 {
756		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageNetscapeServerGatedCrypto)
757	}
758
759	if data.Params.ExtKeyUsage&MicrosoftCommercialCodeSigningExtKeyUsage != 0 {
760		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftCommercialCodeSigning)
761	}
762
763	if data.Params.ExtKeyUsage&MicrosoftKernelCodeSigningExtKeyUsage != 0 {
764		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftKernelCodeSigning)
765	}
766}
767