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 }