github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/cloudflare/cfssl/signer/local/local.go (about)

     1  // Package local implements certificate signature functionality for CFSSL.
     2  package local
     3  
     4  import (
     5  	"bytes"
     6  	"crypto"
     7  	"crypto/rand"
     8  	"encoding/asn1"
     9  	"encoding/hex"
    10  	"encoding/pem"
    11  	"errors"
    12  	"github.com/hellobchain/newcryptosm/http"
    13  	"github.com/hellobchain/newcryptosm/x509"
    14  	"github.com/hellobchain/newcryptosm/x509/pkix"
    15  	"io"
    16  	"math/big"
    17  	"net"
    18  	"net/mail"
    19  	"os"
    20  
    21  	"github.com/google/certificate-transparency-go"
    22  	"github.com/google/certificate-transparency-go/client"
    23  	"github.com/google/certificate-transparency-go/jsonclient"
    24  	"github.com/hellobchain/third_party/cloudflare/cfssl/certdb"
    25  	"github.com/hellobchain/third_party/cloudflare/cfssl/config"
    26  	cferr "github.com/hellobchain/third_party/cloudflare/cfssl/errors"
    27  	"github.com/hellobchain/third_party/cloudflare/cfssl/helpers"
    28  	"github.com/hellobchain/third_party/cloudflare/cfssl/info"
    29  	"github.com/hellobchain/third_party/cloudflare/cfssl/log"
    30  	"github.com/hellobchain/third_party/cloudflare/cfssl/signer"
    31  	"golang.org/x/net/context"
    32  	"time"
    33  )
    34  
    35  // Signer contains a signer that uses the standard library to
    36  // support both ECDSA and RSA CA keys.
    37  type Signer struct {
    38  	ca         *x509.Certificate
    39  	priv       crypto.Signer
    40  	policy     *config.Signing
    41  	sigAlgo    x509.SignatureAlgorithm
    42  	dbAccessor certdb.Accessor
    43  }
    44  
    45  // NewSigner creates a new Signer directly from a
    46  // private key and certificate, with optional policy.
    47  func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.SignatureAlgorithm, policy *config.Signing) (*Signer, error) {
    48  	if policy == nil {
    49  		policy = &config.Signing{
    50  			Profiles: map[string]*config.SigningProfile{},
    51  			Default:  config.DefaultConfig()}
    52  	}
    53  
    54  	if !policy.Valid() {
    55  		return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
    56  	}
    57  
    58  	return &Signer{
    59  		ca:      cert,
    60  		priv:    priv,
    61  		sigAlgo: sigAlgo,
    62  		policy:  policy,
    63  	}, nil
    64  }
    65  
    66  // NewSignerFromFile generates a new local signer from a caFile
    67  // and a caKey file, both PEM encoded.
    68  func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) {
    69  	log.Debug("Loading CA: ", caFile)
    70  	ca, err := helpers.ReadBytes(caFile)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	log.Debug("Loading CA key: ", caKeyFile)
    75  	cakey, err := helpers.ReadBytes(caKeyFile)
    76  	if err != nil {
    77  		return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
    78  	}
    79  
    80  	parsedCa, err := helpers.ParseCertificatePEM(ca)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
    86  	password := []byte(strPassword)
    87  	if strPassword == "" {
    88  		password = nil
    89  	}
    90  
    91  	priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
    92  	if err != nil {
    93  		log.Debug("Malformed private key %v", err)
    94  		return nil, err
    95  	}
    96  
    97  	return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
    98  }
    99  
   100  func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) (cert []byte, err error) {
   101  	var distPoints = template.CRLDistributionPoints
   102  	if distPoints != nil && len(distPoints) > 0 {
   103  		template.CRLDistributionPoints = distPoints
   104  	}
   105  	err = signer.FillTemplate(template, s.policy.Default, profile, notBefore, notAfter)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	var initRoot bool
   111  	if s.ca == nil {
   112  		if !template.IsCA {
   113  			err = cferr.New(cferr.PolicyError, cferr.InvalidRequest)
   114  			return
   115  		}
   116  		template.DNSNames = nil
   117  		template.EmailAddresses = nil
   118  		s.ca = template
   119  		initRoot = true
   120  	}
   121  
   122  	derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
   123  	if err != nil {
   124  		return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
   125  	}
   126  	if initRoot {
   127  		s.ca, err = x509.ParseCertificate(derBytes)
   128  		if err != nil {
   129  			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
   130  		}
   131  	}
   132  
   133  	cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
   134  	log.Infof("signed certificate with serial number %d", template.SerialNumber)
   135  	return
   136  }
   137  
   138  // replaceSliceIfEmpty replaces the contents of replaced with newContents if
   139  // the slice referenced by replaced is empty
   140  func replaceSliceIfEmpty(replaced, newContents *[]string) {
   141  	if len(*replaced) == 0 {
   142  		*replaced = *newContents
   143  	}
   144  }
   145  
   146  // PopulateSubjectFromCSR has functionality similar to Name, except
   147  // it fills the fields of the resulting pkix.Name with req's if the
   148  // subject's corresponding fields are empty
   149  func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name {
   150  	// if no subject, use req
   151  	if s == nil {
   152  		return req
   153  	}
   154  
   155  	name := s.Name()
   156  
   157  	if name.CommonName == "" {
   158  		name.CommonName = req.CommonName
   159  	}
   160  
   161  	replaceSliceIfEmpty(&name.Country, &req.Country)
   162  	replaceSliceIfEmpty(&name.Province, &req.Province)
   163  	replaceSliceIfEmpty(&name.Locality, &req.Locality)
   164  	replaceSliceIfEmpty(&name.Organization, &req.Organization)
   165  	replaceSliceIfEmpty(&name.OrganizationalUnit, &req.OrganizationalUnit)
   166  	if name.SerialNumber == "" {
   167  		name.SerialNumber = req.SerialNumber
   168  	}
   169  	return name
   170  }
   171  
   172  // OverrideHosts fills template's IPAddresses, EmailAddresses, and DNSNames with the
   173  // content of hosts, if it is not nil.
   174  func OverrideHosts(template *x509.Certificate, hosts []string) {
   175  	if hosts != nil {
   176  		template.IPAddresses = []net.IP{}
   177  		template.EmailAddresses = []string{}
   178  		template.DNSNames = []string{}
   179  	}
   180  
   181  	for i := range hosts {
   182  		if ip := net.ParseIP(hosts[i]); ip != nil {
   183  			template.IPAddresses = append(template.IPAddresses, ip)
   184  		} else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil {
   185  			template.EmailAddresses = append(template.EmailAddresses, email.Address)
   186  		} else {
   187  			template.DNSNames = append(template.DNSNames, hosts[i])
   188  		}
   189  	}
   190  
   191  }
   192  
   193  // Sign signs a new certificate based on the PEM-encoded client
   194  // certificate or certificate request with the signing profile,
   195  // specified by profileName.
   196  func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
   197  	profile, err := signer.Profile(s, req.Profile)
   198  	if err != nil {
   199  		return
   200  	}
   201  
   202  	block, _ := pem.Decode([]byte(req.Request))
   203  	if block == nil {
   204  		return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
   205  	}
   206  
   207  	if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
   208  		return nil, cferr.Wrap(cferr.CSRError,
   209  			cferr.BadRequest, errors.New("not a csr"))
   210  	}
   211  
   212  	csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  
   217  	// Copy out only the fields from the CSR authorized by policy.
   218  	safeTemplate := x509.Certificate{}
   219  	// If the profile contains no explicit whitelist, assume that all fields
   220  	// should be copied from the CSR.
   221  	if profile.CSRWhitelist == nil {
   222  		safeTemplate = *csrTemplate
   223  	} else {
   224  		if profile.CSRWhitelist.Subject {
   225  			safeTemplate.Subject = csrTemplate.Subject
   226  		}
   227  		if profile.CSRWhitelist.PublicKeyAlgorithm {
   228  			safeTemplate.PublicKeyAlgorithm = csrTemplate.PublicKeyAlgorithm
   229  		}
   230  		if profile.CSRWhitelist.PublicKey {
   231  			safeTemplate.PublicKey = csrTemplate.PublicKey
   232  		}
   233  		if profile.CSRWhitelist.SignatureAlgorithm {
   234  			safeTemplate.SignatureAlgorithm = csrTemplate.SignatureAlgorithm
   235  		}
   236  		if profile.CSRWhitelist.DNSNames {
   237  			safeTemplate.DNSNames = csrTemplate.DNSNames
   238  		}
   239  		if profile.CSRWhitelist.IPAddresses {
   240  			safeTemplate.IPAddresses = csrTemplate.IPAddresses
   241  		}
   242  		if profile.CSRWhitelist.EmailAddresses {
   243  			safeTemplate.EmailAddresses = csrTemplate.EmailAddresses
   244  		}
   245  	}
   246  
   247  	if req.CRLOverride != "" {
   248  		safeTemplate.CRLDistributionPoints = []string{req.CRLOverride}
   249  	}
   250  
   251  	if safeTemplate.IsCA {
   252  		if !profile.CAConstraint.IsCA {
   253  			log.Error("local signer policy disallows issuing CA certificate")
   254  			return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
   255  		}
   256  
   257  		if s.ca != nil && s.ca.MaxPathLen > 0 {
   258  			if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
   259  				log.Error("local signer certificate disallows CA MaxPathLen extending")
   260  				// do not sign a cert with pathlen > current
   261  				return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
   262  			}
   263  		} else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
   264  			log.Error("local signer certificate disallows issuing CA certificate")
   265  			// signer has pathlen of 0, do not sign more intermediate CAs
   266  			return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
   267  		}
   268  	}
   269  
   270  	OverrideHosts(&safeTemplate, req.Hosts)
   271  	safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
   272  
   273  	// If there is a whitelist, ensure that both the Common Name and SAN DNSNames match
   274  	if profile.NameWhitelist != nil {
   275  		if safeTemplate.Subject.CommonName != "" {
   276  			if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
   277  				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
   278  			}
   279  		}
   280  		for _, name := range safeTemplate.DNSNames {
   281  			if profile.NameWhitelist.Find([]byte(name)) == nil {
   282  				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
   283  			}
   284  		}
   285  		for _, name := range safeTemplate.EmailAddresses {
   286  			if profile.NameWhitelist.Find([]byte(name)) == nil {
   287  				return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
   288  			}
   289  		}
   290  	}
   291  
   292  	if profile.ClientProvidesSerialNumbers {
   293  		if req.Serial == nil {
   294  			return nil, cferr.New(cferr.CertificateError, cferr.MissingSerial)
   295  		}
   296  		safeTemplate.SerialNumber = req.Serial
   297  	} else {
   298  		// RFC 5280 4.1.2.2:
   299  		// Certificate users MUST be able to handle serialNumber
   300  		// values up to 20 octets.  Conforming CAs MUST NOT use
   301  		// serialNumber values longer than 20 octets.
   302  		//
   303  		// If CFSSL is providing the serial numbers, it makes
   304  		// sense to use the max supported size.
   305  		serialNumber := make([]byte, 20)
   306  		_, err = io.ReadFull(rand.Reader, serialNumber)
   307  		if err != nil {
   308  			return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
   309  		}
   310  
   311  		// SetBytes interprets buf as the bytes of a big-endian
   312  		// unsigned integer. The leading byte should be masked
   313  		// off to ensure it isn't negative.
   314  		serialNumber[0] &= 0x7F
   315  
   316  		safeTemplate.SerialNumber = new(big.Int).SetBytes(serialNumber)
   317  	}
   318  
   319  	if len(req.Extensions) > 0 {
   320  		for _, ext := range req.Extensions {
   321  			oid := asn1.ObjectIdentifier(ext.ID)
   322  			if !profile.ExtensionWhitelist[oid.String()] {
   323  				return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
   324  			}
   325  
   326  			rawValue, err := hex.DecodeString(ext.Value)
   327  			if err != nil {
   328  				return nil, cferr.Wrap(cferr.CertificateError, cferr.InvalidRequest, err)
   329  			}
   330  
   331  			safeTemplate.ExtraExtensions = append(safeTemplate.ExtraExtensions, pkix.Extension{
   332  				Id:       oid,
   333  				Critical: ext.Critical,
   334  				Value:    rawValue,
   335  			})
   336  		}
   337  	}
   338  
   339  	var certTBS = safeTemplate
   340  
   341  	if len(profile.CTLogServers) > 0 {
   342  		// Add a poison extension which prevents validation
   343  		var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
   344  		var poisonedPreCert = certTBS
   345  		poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
   346  		cert, err = s.sign(&poisonedPreCert, profile, req.NotBefore, req.NotAfter)
   347  		if err != nil {
   348  			return
   349  		}
   350  
   351  		derCert, _ := pem.Decode(cert)
   352  		prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
   353  		var sctList []ct.SignedCertificateTimestamp
   354  
   355  		for _, server := range profile.CTLogServers {
   356  			log.Infof("submitting poisoned precertificate to %s", server)
   357  			ctclient, err := client.New(server, nil, jsonclient.Options{})
   358  			if err != nil {
   359  				return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
   360  			}
   361  			var resp *ct.SignedCertificateTimestamp
   362  			ctx := context.Background()
   363  			resp, err = ctclient.AddPreChain(ctx, prechain)
   364  			if err != nil {
   365  				return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
   366  			}
   367  			sctList = append(sctList, *resp)
   368  		}
   369  
   370  		var serializedSCTList []byte
   371  		serializedSCTList, err = helpers.SerializeSCTList(sctList)
   372  		if err != nil {
   373  			return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
   374  		}
   375  
   376  		// Serialize again as an octet string before embedding
   377  		serializedSCTList, err = asn1.Marshal(serializedSCTList)
   378  		if err != nil {
   379  			return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
   380  		}
   381  
   382  		var SCTListExtension = pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedSCTList}
   383  		certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
   384  	}
   385  	var signedCert []byte
   386  	signedCert, err = s.sign(&certTBS, profile, req.NotBefore, req.NotAfter)
   387  	if err != nil {
   388  		return nil, err
   389  	}
   390  
   391  	// Get the AKI from signedCert.  This is required to support Go 1.9+.
   392  	// In prior versions of Go, x509.CreateCertificate updated the
   393  	// AuthorityKeyId of certTBS.
   394  	parsedCert, _ := helpers.ParseCertificatePEM(signedCert)
   395  
   396  	if s.dbAccessor != nil {
   397  		var certRecord = certdb.CertificateRecord{
   398  			Serial: certTBS.SerialNumber.String(),
   399  			// this relies on the specific behavior of x509.CreateCertificate
   400  			// which sets the AuthorityKeyId from the signer's SubjectKeyId
   401  			AKI:     hex.EncodeToString(parsedCert.AuthorityKeyId),
   402  			CALabel: req.Label,
   403  			Status:  "good",
   404  			Expiry:  certTBS.NotAfter,
   405  			PEM:     string(signedCert),
   406  		}
   407  
   408  		err = s.dbAccessor.InsertCertificate(certRecord)
   409  		if err != nil {
   410  			return nil, err
   411  		}
   412  		log.Debug("saved certificate with serial number ", certTBS.SerialNumber)
   413  	}
   414  
   415  	return signedCert, nil
   416  }
   417  
   418  // Info return a populated info.Resp struct or an error.
   419  func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
   420  	cert, err := s.Certificate(req.Label, req.Profile)
   421  	if err != nil {
   422  		return
   423  	}
   424  
   425  	profile, err := signer.Profile(s, req.Profile)
   426  	if err != nil {
   427  		return
   428  	}
   429  
   430  	resp = new(info.Resp)
   431  	if cert.Raw != nil {
   432  		resp.Certificate = string(bytes.TrimSpace(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})))
   433  	}
   434  	resp.Usage = profile.Usage
   435  	resp.ExpiryString = profile.ExpiryString
   436  
   437  	return
   438  }
   439  
   440  // SigAlgo returns the RSA signer's signature algorithm.
   441  func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
   442  	return s.sigAlgo
   443  }
   444  
   445  // Certificate returns the signer's certificate.
   446  func (s *Signer) Certificate(label, profile string) (*x509.Certificate, error) {
   447  	cert := *s.ca
   448  	return &cert, nil
   449  }
   450  
   451  // SetPolicy sets the signer's signature policy.
   452  func (s *Signer) SetPolicy(policy *config.Signing) {
   453  	s.policy = policy
   454  }
   455  
   456  // SetDBAccessor sets the signers' cert db accessor
   457  func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
   458  	s.dbAccessor = dba
   459  }
   460  
   461  // GetDBAccessor returns the signers' cert db accessor
   462  func (s *Signer) GetDBAccessor() certdb.Accessor {
   463  	return s.dbAccessor
   464  }
   465  
   466  // SetReqModifier does nothing for local
   467  func (s *Signer) SetReqModifier(func(*http.Request, []byte)) {
   468  	// noop
   469  }
   470  
   471  // Policy returns the signer's policy.
   472  func (s *Signer) Policy() *config.Signing {
   473  	return s.policy
   474  }