...

Source file src/github.com/sigstore/timestamp-authority/pkg/signer/memory.go

Documentation: github.com/sigstore/timestamp-authority/pkg/signer

     1  // Copyright 2022 The Sigstore Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package signer
    16  
    17  import (
    18  	"crypto"
    19  	"crypto/ecdsa"
    20  	"crypto/elliptic"
    21  	"crypto/rand"
    22  	"crypto/x509"
    23  	"crypto/x509/pkix"
    24  	"encoding/asn1"
    25  	"fmt"
    26  	"time"
    27  
    28  	"github.com/pkg/errors"
    29  	"github.com/sigstore/sigstore/pkg/cryptoutils"
    30  	tsx509 "github.com/sigstore/timestamp-authority/pkg/x509"
    31  )
    32  
    33  // NewTimestampingCertWithChain generates an in-memory certificate chain.
    34  func NewTimestampingCertWithChain(signer crypto.Signer) ([]*x509.Certificate, error) {
    35  	now := time.Now()
    36  
    37  	// generate root
    38  	rootPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    39  	if err != nil {
    40  		return nil, fmt.Errorf("generating in-memory root key")
    41  	}
    42  	sn, err := cryptoutils.GenerateSerialNumber()
    43  	if err != nil {
    44  		return nil, fmt.Errorf("generating root serial number: %w", err)
    45  	}
    46  	rootCA := &x509.Certificate{
    47  		SerialNumber: sn,
    48  		Subject: pkix.Name{
    49  			CommonName:   "Test TSA Root",
    50  			Organization: []string{"local"},
    51  		},
    52  		NotBefore:             now.Add(-5 * time.Minute),
    53  		NotAfter:              now.AddDate(10, 0, 0),
    54  		IsCA:                  true,
    55  		BasicConstraintsValid: true,
    56  		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
    57  	}
    58  	rootCACertDER, err := x509.CreateCertificate(rand.Reader, rootCA, rootCA, rootPriv.Public(), rootPriv)
    59  	if err != nil {
    60  		return nil, fmt.Errorf("creating self-signed root CA: %w", err)
    61  	}
    62  	rootCACert, err := x509.ParseCertificate(rootCACertDER)
    63  	if err != nil {
    64  		return nil, fmt.Errorf("parsing root CA certificate: %w", err)
    65  	}
    66  
    67  	// generate subordinate
    68  	sn, err = cryptoutils.GenerateSerialNumber()
    69  	if err != nil {
    70  		return nil, fmt.Errorf("generating subordinate serial number: %w", err)
    71  	}
    72  	subPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    73  	if err != nil {
    74  		return nil, fmt.Errorf("generating in-memory subordinate key")
    75  	}
    76  	subCA := &x509.Certificate{
    77  		SerialNumber: sn,
    78  		Subject: pkix.Name{
    79  			CommonName:   "Test TSA Intermediate",
    80  			Organization: []string{"local"},
    81  		},
    82  		NotBefore:             now.Add(-5 * time.Minute),
    83  		NotAfter:              now.AddDate(10, 0, 0),
    84  		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
    85  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
    86  		BasicConstraintsValid: true,
    87  		IsCA:                  true,
    88  	}
    89  	subCACertDER, err := x509.CreateCertificate(rand.Reader, subCA, rootCACert, subPriv.Public(), rootPriv)
    90  	if err != nil {
    91  		return nil, fmt.Errorf("creating self-signed subordinate CA: %w", err)
    92  	}
    93  	subCACert, err := x509.ParseCertificate(subCACertDER)
    94  	if err != nil {
    95  		return nil, fmt.Errorf("parsing subordinate CA certificate: %w", err)
    96  	}
    97  
    98  	// generate leaf
    99  	sn, err = cryptoutils.GenerateSerialNumber()
   100  	if err != nil {
   101  		return nil, fmt.Errorf("generating leaf serial number: %w", err)
   102  	}
   103  	timestampExt, err := asn1.Marshal([]asn1.ObjectIdentifier{tsx509.EKUTimestampingOID})
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	skid, err := cryptoutils.SKID(signer.Public())
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	cert := &x509.Certificate{
   114  		SerialNumber: sn,
   115  		Subject: pkix.Name{
   116  			CommonName:   "Test TSA Timestamping",
   117  			Organization: []string{"local"},
   118  		},
   119  		SubjectKeyId: skid,
   120  		NotBefore:    now.Add(-3 * time.Minute),
   121  		NotAfter:     now.AddDate(9, 0, 0),
   122  		IsCA:         false,
   123  		KeyUsage:     x509.KeyUsageDigitalSignature,
   124  		// set EKU to x509.ExtKeyUsageTimeStamping but with a critical bit
   125  		ExtraExtensions: []pkix.Extension{
   126  			{
   127  				Id:       tsx509.EKUOID,
   128  				Critical: true,
   129  				Value:    timestampExt,
   130  			},
   131  		},
   132  	}
   133  	certDER, err := x509.CreateCertificate(rand.Reader, cert, subCACert, signer.Public(), subPriv)
   134  	if err != nil {
   135  		return nil, errors.Wrap(err, "creating tsa certificate")
   136  	}
   137  	tsaCert, err := x509.ParseCertificate(certDER)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  
   142  	// Verify and return the certificate chain
   143  	root := x509.NewCertPool()
   144  	root.AddCert(rootCACert)
   145  	intermediate := x509.NewCertPool()
   146  	intermediate.AddCert(subCACert)
   147  	verifyOptions := x509.VerifyOptions{
   148  		Roots:         root,
   149  		Intermediates: intermediate,
   150  		KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageTimeStamping},
   151  	}
   152  	if _, err = tsaCert.Verify(verifyOptions); err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	return []*x509.Certificate{tsaCert, subCACert, rootCACert}, nil
   157  }
   158  

View as plain text