github.com/openshift/installer@v1.4.17/pkg/asset/tls/tls.go (about)

     1  package tls
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/rsa"
     9  	"crypto/sha1"
    10  	"crypto/x509"
    11  	"crypto/x509/pkix"
    12  	"encoding/asn1"
    13  	"math"
    14  	"math/big"
    15  	"net"
    16  	"time"
    17  
    18  	"github.com/pkg/errors"
    19  	"github.com/sirupsen/logrus"
    20  )
    21  
    22  const (
    23  	keySize = 2048
    24  
    25  	// ValidityOneDay sets the validity of a cert to 24 hours.
    26  	ValidityOneDay = time.Hour * 24
    27  
    28  	// ValidityOneYear sets the validity of a cert to 1 year.
    29  	ValidityOneYear = ValidityOneDay * 365
    30  
    31  	// ValidityTenYears sets the validity of a cert to 10 years.
    32  	ValidityTenYears = ValidityOneYear * 10
    33  )
    34  
    35  // CertCfg contains all needed fields to configure a new certificate
    36  type CertCfg struct {
    37  	DNSNames     []string
    38  	ExtKeyUsages []x509.ExtKeyUsage
    39  	IPAddresses  []net.IP
    40  	KeyUsages    x509.KeyUsage
    41  	Subject      pkix.Name
    42  	Validity     time.Duration
    43  	IsCA         bool
    44  }
    45  
    46  // rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
    47  type rsaPublicKey struct {
    48  	N *big.Int
    49  	E int
    50  }
    51  
    52  // PrivateKey generates an RSA Private key and returns the value
    53  func PrivateKey() (*rsa.PrivateKey, error) {
    54  	rsaKey, err := rsa.GenerateKey(rand.Reader, keySize)
    55  	if err != nil {
    56  		return nil, errors.Wrap(err, "error generating RSA private key")
    57  	}
    58  
    59  	return rsaKey, nil
    60  }
    61  
    62  // SelfSignedCertificate creates a self signed certificate
    63  func SelfSignedCertificate(cfg *CertCfg, key *rsa.PrivateKey) (*x509.Certificate, error) {
    64  	serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	cert := x509.Certificate{
    69  		BasicConstraintsValid: true,
    70  		IsCA:                  cfg.IsCA,
    71  		KeyUsage:              cfg.KeyUsages,
    72  		NotAfter:              time.Now().Add(cfg.Validity),
    73  		NotBefore:             time.Now(),
    74  		SerialNumber:          serial,
    75  		Subject:               cfg.Subject,
    76  	}
    77  	// verifies that the CN and/or OU for the cert is set
    78  	if len(cfg.Subject.CommonName) == 0 || len(cfg.Subject.OrganizationalUnit) == 0 {
    79  		return nil, errors.Errorf("certification's subject is not set, or invalid")
    80  	}
    81  	pub := key.Public()
    82  	cert.SubjectKeyId, err = generateSubjectKeyID(pub)
    83  	if err != nil {
    84  		return nil, errors.Wrap(err, "failed to set subject key identifier")
    85  	}
    86  	certBytes, err := x509.CreateCertificate(rand.Reader, &cert, &cert, key.Public(), key)
    87  	if err != nil {
    88  		return nil, errors.Wrap(err, "failed to create certificate")
    89  	}
    90  	return x509.ParseCertificate(certBytes)
    91  }
    92  
    93  // SignedCertificate creates a new X.509 certificate based on a template.
    94  func SignedCertificate(
    95  	cfg *CertCfg,
    96  	csr *x509.CertificateRequest,
    97  	key *rsa.PrivateKey,
    98  	caCert *x509.Certificate,
    99  	caKey *rsa.PrivateKey,
   100  ) (*x509.Certificate, error) {
   101  	serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	certTmpl := x509.Certificate{
   107  		DNSNames:              csr.DNSNames,
   108  		ExtKeyUsage:           cfg.ExtKeyUsages,
   109  		IPAddresses:           csr.IPAddresses,
   110  		KeyUsage:              cfg.KeyUsages,
   111  		NotAfter:              time.Now().Add(cfg.Validity),
   112  		NotBefore:             caCert.NotBefore,
   113  		SerialNumber:          serial,
   114  		Subject:               csr.Subject,
   115  		IsCA:                  cfg.IsCA,
   116  		Version:               3,
   117  		BasicConstraintsValid: true,
   118  	}
   119  	pub := key.Public()
   120  	certTmpl.SubjectKeyId, err = generateSubjectKeyID(pub)
   121  	if err != nil {
   122  		return nil, errors.Wrap(err, "failed to set subject key identifier")
   123  	}
   124  	certBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
   125  	if err != nil {
   126  		return nil, errors.Wrap(err, "failed to create x509 certificate")
   127  	}
   128  	return x509.ParseCertificate(certBytes)
   129  }
   130  
   131  // generateSubjectKeyID generates a SHA-1 hash of the subject public key.
   132  func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
   133  	var publicKeyBytes []byte
   134  	var err error
   135  
   136  	switch pub := pub.(type) {
   137  	case *rsa.PublicKey:
   138  		publicKeyBytes, err = asn1.Marshal(rsaPublicKey{N: pub.N, E: pub.E})
   139  		if err != nil {
   140  			return nil, errors.Wrap(err, "failed to Marshal ans1 public key")
   141  		}
   142  	case *ecdsa.PublicKey:
   143  		publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
   144  	default:
   145  		return nil, errors.New("only RSA and ECDSA public keys supported")
   146  	}
   147  
   148  	hash := sha1.Sum(publicKeyBytes)
   149  	return hash[:], nil
   150  }
   151  
   152  // GenerateSignedCertificate generate a key and cert defined by CertCfg and signed by CA.
   153  func GenerateSignedCertificate(caKey *rsa.PrivateKey, caCert *x509.Certificate,
   154  	cfg *CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) {
   155  
   156  	// create a private key
   157  	key, err := PrivateKey()
   158  	if err != nil {
   159  		return nil, nil, errors.Wrap(err, "failed to generate private key")
   160  	}
   161  
   162  	// create a CSR
   163  	csrTmpl := x509.CertificateRequest{Subject: cfg.Subject, DNSNames: cfg.DNSNames, IPAddresses: cfg.IPAddresses}
   164  	csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTmpl, key)
   165  	if err != nil {
   166  		return nil, nil, errors.Wrap(err, "failed to create certificate request")
   167  	}
   168  
   169  	csr, err := x509.ParseCertificateRequest(csrBytes)
   170  	if err != nil {
   171  		logrus.Debugf("Failed to parse x509 certificate request: %s", err)
   172  		return nil, nil, errors.Wrap(err, "error parsing x509 certificate request")
   173  	}
   174  
   175  	// create a cert
   176  	cert, err := SignedCertificate(cfg, csr, key, caCert, caKey)
   177  	if err != nil {
   178  		logrus.Debugf("Failed to create a signed certificate: %s", err)
   179  		return nil, nil, errors.Wrap(err, "failed to create a signed certificate")
   180  	}
   181  	return key, cert, nil
   182  }
   183  
   184  // GenerateSelfSignedCertificate generates a key/cert pair defined by CertCfg.
   185  func GenerateSelfSignedCertificate(cfg *CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) {
   186  	key, err := PrivateKey()
   187  	if err != nil {
   188  		logrus.Debugf("Failed to generate a private key: %s", err)
   189  		return nil, nil, errors.Wrap(err, "failed to generate private key")
   190  	}
   191  
   192  	crt, err := SelfSignedCertificate(cfg, key)
   193  	if err != nil {
   194  		logrus.Debugf("Failed to create self-signed certificate: %s", err)
   195  		return nil, nil, errors.Wrap(err, "failed to create self-signed certificate")
   196  	}
   197  	return key, crt, nil
   198  }