// FillTemplate is a utility function that tries to load as much of // the certificate template as possible from the profiles and current // template. It fills in the key uses, expiration, revocation URLs, // serial number, and SKI. func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.SigningProfile, serialSeq string) error { ski, err := ComputeSKI(template) var ( eku []x509.ExtKeyUsage ku x509.KeyUsage backdate time.Duration expiry time.Duration notBefore time.Time notAfter time.Time crlURL, ocspURL string ) // The third value returned from Usages is a list of unknown key usages. // This should be used when validating the profile at load, and isn't used // here. ku, eku, _ = profile.Usages() if profile.IssuerURL == nil { profile.IssuerURL = defaultProfile.IssuerURL } if ku == 0 && len(eku) == 0 { return cferr.New(cferr.PolicyError, cferr.NoKeyUsages) } if expiry = profile.Expiry; expiry == 0 { expiry = defaultProfile.Expiry } if crlURL = profile.CRL; crlURL == "" { crlURL = defaultProfile.CRL } if ocspURL = profile.OCSP; ocspURL == "" { ocspURL = defaultProfile.OCSP } if backdate = profile.Backdate; backdate == 0 { backdate = -5 * time.Minute } else { backdate = -1 * profile.Backdate } if !profile.NotBefore.IsZero() { notBefore = profile.NotBefore.UTC() } else { notBefore = time.Now().Round(time.Minute).Add(backdate).UTC() } if !profile.NotAfter.IsZero() { notAfter = profile.NotAfter.UTC() } else { notAfter = notBefore.Add(expiry).UTC() } serialNumber, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) if err != nil { return cferr.Wrap(cferr.CertificateError, cferr.Unknown, err) } if serialSeq != "" { randomPart := fmt.Sprintf("%016X", serialNumber) // 016 ensures we're left-0-padded _, ok := serialNumber.SetString(serialSeq+randomPart, 16) if !ok { return cferr.Wrap(cferr.CertificateError, cferr.SerialSeqParseError, err) } } template.SerialNumber = serialNumber template.NotBefore = notBefore template.NotAfter = notAfter template.KeyUsage = ku template.ExtKeyUsage = eku template.BasicConstraintsValid = true template.IsCA = profile.CA template.SubjectKeyId = ski if ocspURL != "" { template.OCSPServer = []string{ocspURL} } if crlURL != "" { template.CRLDistributionPoints = []string{crlURL} } if len(profile.IssuerURL) != 0 { template.IssuingCertificateURL = profile.IssuerURL } if len(profile.Policies) != 0 { template.PolicyIdentifiers = profile.Policies } if profile.OCSPNoCheck { ocspNoCheckExtension := pkix.Extension{ Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5}, Critical: false, Value: []byte{0x05, 0x00}, } template.ExtraExtensions = append(template.ExtraExtensions, ocspNoCheckExtension) } return nil }