blob: 4bc637b45a4afe0b101c87e254c23cb4e5b9e9e1 [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
Serge Bazanski9411f7c2021-03-10 13:12:53 +01002// SPDX-License-Identifier: Apache-2.0
Serge Bazanski9411f7c2021-03-10 13:12:53 +01003
4package pki
5
6import (
7 "context"
8 "crypto/ed25519"
9 "crypto/rand"
10 "crypto/x509"
11 "fmt"
12 "math/big"
13 "time"
14
Lorenz Brund13c1c62022-03-30 19:58:58 +020015 clientv3 "go.etcd.io/etcd/client/v3"
Serge Bazanski9411f7c2021-03-10 13:12:53 +010016)
17
Tim Windelschmidt7fd64f62025-06-29 02:32:31 +020018var (
19 // From RFC 5280 Section 4.1.2.5
20 UnknownNotAfter = time.Unix(253402300799, 0)
21)
22
Serge Bazanski9411f7c2021-03-10 13:12:53 +010023// Issuer is an entity that can issue certificates. This interface is
24// implemented by SelfSigned, which is an issuer that emits self-signed
25// certificates, and any other Certificate that has been created with CA(),
26// which makes this Certificate act as a CA and issue (sign) ceritficates.
27type Issuer interface {
Serge Bazanski216fe7b2021-05-21 18:36:16 +020028 // CACertificate returns the DER-encoded x509 certificate of the CA that
29 // will sign certificates when Issue is called, or nil if this is
30 // self-signing issuer.
Serge Bazanski9411f7c2021-03-10 13:12:53 +010031 CACertificate(ctx context.Context, kv clientv3.KV) ([]byte, error)
Serge Bazanski52538842021-08-11 16:22:41 +020032 // Issue will generate a certificate signed by the Issuer. The returned
33 // certificate is x509 DER-encoded.
34 Issue(ctx context.Context, req *Certificate, kv clientv3.KV) (cert []byte, err error)
Serge Bazanski9411f7c2021-03-10 13:12:53 +010035}
36
Serge Bazanski216fe7b2021-05-21 18:36:16 +020037// issueCertificate is a generic low level certificate-and-key issuance
Serge Bazanski52538842021-08-11 16:22:41 +020038// function. If ca is null, the certificate will be self-signed. The returned
39// certificate is DER-encoded
40func issueCertificate(req *Certificate, ca *x509.Certificate, caKey ed25519.PrivateKey) (cert []byte, err error) {
Serge Bazanski9411f7c2021-03-10 13:12:53 +010041 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 127)
42 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
43 if err != nil {
44 err = fmt.Errorf("failed to generate serial number: %w", err)
45 return
46 }
47
Serge Bazanski52538842021-08-11 16:22:41 +020048 req.Template.SerialNumber = serialNumber
49 req.Template.NotBefore = time.Now()
Serge Bazanskid7d6e022021-09-01 15:03:06 +020050 req.Template.NotAfter = UnknownNotAfter
Serge Bazanski52538842021-08-11 16:22:41 +020051 req.Template.BasicConstraintsValid = true
Serge Bazanski9411f7c2021-03-10 13:12:53 +010052
Serge Bazanski216fe7b2021-05-21 18:36:16 +020053 // Set the AuthorityKeyID to the SKID of the signing certificate (or self,
54 // if self-signing).
Serge Bazanski52538842021-08-11 16:22:41 +020055 if ca != nil {
Lorenz Brun237cf402022-07-04 12:14:37 +000056 req.Template.AuthorityKeyId = ca.SubjectKeyId
Serge Bazanski9411f7c2021-03-10 13:12:53 +010057 } else {
Serge Bazanski52538842021-08-11 16:22:41 +020058 req.Template.AuthorityKeyId = req.Template.SubjectKeyId
59 ca = &req.Template
Serge Bazanski9411f7c2021-03-10 13:12:53 +010060 }
61
Serge Bazanski52538842021-08-11 16:22:41 +020062 return x509.CreateCertificate(rand.Reader, &req.Template, ca, req.PublicKey, caKey)
Serge Bazanski9411f7c2021-03-10 13:12:53 +010063}
64
65type selfSigned struct{}
66
67var (
68 // SelfSigned is an Issuer that generates self-signed certificates.
69 SelfSigned = &selfSigned{}
70)
71
72// Issue will generate a key and certificate that is self-signed.
Serge Bazanski52538842021-08-11 16:22:41 +020073func (s *selfSigned) Issue(ctx context.Context, req *Certificate, kv clientv3.KV) (cert []byte, err error) {
74 if err := req.ensureKey(ctx, kv); err != nil {
75 return nil, err
76 }
77 if req.PrivateKey == nil {
78 return nil, fmt.Errorf("cannot issue self-signed certificate without a private key")
79 }
80 return issueCertificate(req, nil, req.PrivateKey)
Serge Bazanski9411f7c2021-03-10 13:12:53 +010081}
82
83// CACertificate returns nil for self-signed issuers.
84func (s *selfSigned) CACertificate(ctx context.Context, kv clientv3.KV) ([]byte, error) {
85 return nil, nil
86}
87
88// Issue will generate a key and certificate that is signed by this
89// Certificate, if the Certificate is a CA.
Serge Bazanski52538842021-08-11 16:22:41 +020090func (c *Certificate) Issue(ctx context.Context, req *Certificate, kv clientv3.KV) (cert []byte, err error) {
91 if err := c.ensureKey(ctx, kv); err != nil {
92 return nil, fmt.Errorf("could not ensure CA %q key exists: %w", c.Name, err)
93 }
94 if err := req.ensureKey(ctx, kv); err != nil {
95 return nil, fmt.Errorf("could not subject %q key exists: %w", req.Name, err)
96 }
97 if c.PrivateKey == nil {
98 return nil, fmt.Errorf("cannot use certificate without private key as CA")
99 }
100
101 caCert, err := c.ensure(ctx, kv)
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100102 if err != nil {
Serge Bazanski52538842021-08-11 16:22:41 +0200103 return nil, fmt.Errorf("could not ensure CA %q certificate exists: %w", c.Name, err)
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100104 }
105
106 ca, err := x509.ParseCertificate(caCert)
107 if err != nil {
Serge Bazanski52538842021-08-11 16:22:41 +0200108 return nil, fmt.Errorf("could not parse CA certificate: %w", err)
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100109 }
110 // Ensure only one level of CAs exist, and that they are created explicitly.
Serge Bazanski52538842021-08-11 16:22:41 +0200111 req.Template.IsCA = false
112 return issueCertificate(req, ca, c.PrivateKey)
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100113}
114
115// CACertificate returns the DER encoded x509 form of this Certificate that
116// will be the used to issue child certificates.
117func (c *Certificate) CACertificate(ctx context.Context, kv clientv3.KV) ([]byte, error) {
Serge Bazanski52538842021-08-11 16:22:41 +0200118 return c.ensure(ctx, kv)
Serge Bazanski9411f7c2021-03-10 13:12:53 +0100119}