1package certutil 2 3import ( 4 "bytes" 5 "crypto" 6 "crypto/ecdsa" 7 "crypto/elliptic" 8 "crypto/rand" 9 "crypto/rsa" 10 "crypto/sha1" 11 "crypto/x509" 12 "crypto/x509/pkix" 13 "encoding/asn1" 14 "encoding/pem" 15 "errors" 16 "fmt" 17 "math/big" 18 "net" 19 "net/url" 20 "strconv" 21 "strings" 22 "time" 23 24 "github.com/hashicorp/errwrap" 25 "github.com/hashicorp/vault/sdk/helper/errutil" 26 "github.com/hashicorp/vault/sdk/helper/jsonutil" 27 "github.com/mitchellh/mapstructure" 28 "golang.org/x/crypto/cryptobyte" 29 cbasn1 "golang.org/x/crypto/cryptobyte/asn1" 30) 31 32// GetHexFormatted returns the byte buffer formatted in hex with 33// the specified separator between bytes. 34func GetHexFormatted(buf []byte, sep string) string { 35 var ret bytes.Buffer 36 for _, cur := range buf { 37 if ret.Len() > 0 { 38 fmt.Fprintf(&ret, sep) 39 } 40 fmt.Fprintf(&ret, "%02x", cur) 41 } 42 return ret.String() 43} 44 45// ParseHexFormatted returns the raw bytes from a formatted hex string 46func ParseHexFormatted(in, sep string) []byte { 47 var ret bytes.Buffer 48 var err error 49 var inBits int64 50 inBytes := strings.Split(in, sep) 51 for _, inByte := range inBytes { 52 if inBits, err = strconv.ParseInt(inByte, 16, 8); err != nil { 53 return nil 54 } 55 ret.WriteByte(byte(inBits)) 56 } 57 return ret.Bytes() 58} 59 60// GetSubjKeyID returns the subject key ID, e.g. the SHA1 sum 61// of the marshaled public key 62func GetSubjKeyID(privateKey crypto.Signer) ([]byte, error) { 63 if privateKey == nil { 64 return nil, errutil.InternalError{Err: "passed-in private key is nil"} 65 } 66 67 marshaledKey, err := x509.MarshalPKIXPublicKey(privateKey.Public()) 68 if err != nil { 69 return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} 70 } 71 72 subjKeyID := sha1.Sum(marshaledKey) 73 74 return subjKeyID[:], nil 75} 76 77// ParsePKIMap takes a map (for instance, the Secret.Data 78// returned from the PKI backend) and returns a ParsedCertBundle. 79func ParsePKIMap(data map[string]interface{}) (*ParsedCertBundle, error) { 80 result := &CertBundle{} 81 err := mapstructure.Decode(data, result) 82 if err != nil { 83 return nil, errutil.UserError{Err: err.Error()} 84 } 85 86 return result.ToParsedCertBundle() 87} 88 89// ParsePKIJSON takes a JSON-encoded string and returns a ParsedCertBundle. 90// 91// This can be either the output of an 92// issue call from the PKI backend or just its data member; or, 93// JSON not coming from the PKI backend. 94func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) { 95 result := &CertBundle{} 96 err := jsonutil.DecodeJSON(input, &result) 97 98 if err == nil { 99 return result.ToParsedCertBundle() 100 } 101 102 var secret Secret 103 err = jsonutil.DecodeJSON(input, &secret) 104 105 if err == nil { 106 return ParsePKIMap(secret.Data) 107 } 108 109 return nil, errutil.UserError{Err: "unable to parse out of either secret data or a secret object"} 110} 111 112// ParsePEMBundle takes a string of concatenated PEM-format certificate 113// and private key values and decodes/parses them, checking validity along 114// the way. The first certificate must be the subject certificate and issuing 115// certificates may follow. There must be at most one private key. 116func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) { 117 if len(pemBundle) == 0 { 118 return nil, errutil.UserError{Err: "empty pem bundle"} 119 } 120 121 pemBytes := []byte(pemBundle) 122 var pemBlock *pem.Block 123 parsedBundle := &ParsedCertBundle{} 124 var certPath []*CertBlock 125 126 for len(pemBytes) > 0 { 127 pemBlock, pemBytes = pem.Decode(pemBytes) 128 if pemBlock == nil { 129 return nil, errutil.UserError{Err: "no data found in PEM block"} 130 } 131 132 if signer, err := x509.ParseECPrivateKey(pemBlock.Bytes); err == nil { 133 if parsedBundle.PrivateKeyType != UnknownPrivateKey { 134 return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"} 135 } 136 parsedBundle.PrivateKeyFormat = ECBlock 137 parsedBundle.PrivateKeyType = ECPrivateKey 138 parsedBundle.PrivateKeyBytes = pemBlock.Bytes 139 parsedBundle.PrivateKey = signer 140 141 } else if signer, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil { 142 if parsedBundle.PrivateKeyType != UnknownPrivateKey { 143 return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"} 144 } 145 parsedBundle.PrivateKeyType = RSAPrivateKey 146 parsedBundle.PrivateKeyFormat = PKCS1Block 147 parsedBundle.PrivateKeyBytes = pemBlock.Bytes 148 parsedBundle.PrivateKey = signer 149 } else if signer, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes); err == nil { 150 parsedBundle.PrivateKeyFormat = PKCS8Block 151 152 if parsedBundle.PrivateKeyType != UnknownPrivateKey { 153 return nil, errutil.UserError{Err: "More than one private key given; provide only one private key in the bundle"} 154 } 155 switch signer := signer.(type) { 156 case *rsa.PrivateKey: 157 parsedBundle.PrivateKey = signer 158 parsedBundle.PrivateKeyType = RSAPrivateKey 159 parsedBundle.PrivateKeyBytes = pemBlock.Bytes 160 case *ecdsa.PrivateKey: 161 parsedBundle.PrivateKey = signer 162 parsedBundle.PrivateKeyType = ECPrivateKey 163 parsedBundle.PrivateKeyBytes = pemBlock.Bytes 164 } 165 } else if certificates, err := x509.ParseCertificates(pemBlock.Bytes); err == nil { 166 certPath = append(certPath, &CertBlock{ 167 Certificate: certificates[0], 168 Bytes: pemBlock.Bytes, 169 }) 170 } 171 } 172 173 for i, certBlock := range certPath { 174 if i == 0 { 175 parsedBundle.Certificate = certBlock.Certificate 176 parsedBundle.CertificateBytes = certBlock.Bytes 177 } else { 178 parsedBundle.CAChain = append(parsedBundle.CAChain, certBlock) 179 } 180 } 181 182 if err := parsedBundle.Verify(); err != nil { 183 return nil, errutil.UserError{Err: fmt.Sprintf("verification of parsed bundle failed: %s", err)} 184 } 185 186 return parsedBundle, nil 187} 188 189// GeneratePrivateKey generates a private key with the specified type and key bits 190func GeneratePrivateKey(keyType string, keyBits int, container ParsedPrivateKeyContainer) error { 191 var err error 192 var privateKeyType PrivateKeyType 193 var privateKeyBytes []byte 194 var privateKey crypto.Signer 195 196 switch keyType { 197 case "rsa": 198 privateKeyType = RSAPrivateKey 199 privateKey, err = rsa.GenerateKey(rand.Reader, keyBits) 200 if err != nil { 201 return errutil.InternalError{Err: fmt.Sprintf("error generating RSA private key: %v", err)} 202 } 203 privateKeyBytes = x509.MarshalPKCS1PrivateKey(privateKey.(*rsa.PrivateKey)) 204 case "ec": 205 privateKeyType = ECPrivateKey 206 var curve elliptic.Curve 207 switch keyBits { 208 case 224: 209 curve = elliptic.P224() 210 case 256: 211 curve = elliptic.P256() 212 case 384: 213 curve = elliptic.P384() 214 case 521: 215 curve = elliptic.P521() 216 default: 217 return errutil.UserError{Err: fmt.Sprintf("unsupported bit length for EC key: %d", keyBits)} 218 } 219 privateKey, err = ecdsa.GenerateKey(curve, rand.Reader) 220 if err != nil { 221 return errutil.InternalError{Err: fmt.Sprintf("error generating EC private key: %v", err)} 222 } 223 privateKeyBytes, err = x509.MarshalECPrivateKey(privateKey.(*ecdsa.PrivateKey)) 224 if err != nil { 225 return errutil.InternalError{Err: fmt.Sprintf("error marshalling EC private key: %v", err)} 226 } 227 default: 228 return errutil.UserError{Err: fmt.Sprintf("unknown key type: %s", keyType)} 229 } 230 231 container.SetParsedPrivateKey(privateKey, privateKeyType, privateKeyBytes) 232 return nil 233} 234 235// GenerateSerialNumber generates a serial number suitable for a certificate 236func GenerateSerialNumber() (*big.Int, error) { 237 serial, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil)) 238 if err != nil { 239 return nil, errutil.InternalError{Err: fmt.Sprintf("error generating serial number: %v", err)} 240 } 241 return serial, nil 242} 243 244// ComparePublicKeys compares two public keys and returns true if they match 245func ComparePublicKeys(key1Iface, key2Iface crypto.PublicKey) (bool, error) { 246 switch key1Iface.(type) { 247 case *rsa.PublicKey: 248 key1 := key1Iface.(*rsa.PublicKey) 249 key2, ok := key2Iface.(*rsa.PublicKey) 250 if !ok { 251 return false, fmt.Errorf("key types do not match: %T and %T", key1Iface, key2Iface) 252 } 253 if key1.N.Cmp(key2.N) != 0 || 254 key1.E != key2.E { 255 return false, nil 256 } 257 return true, nil 258 259 case *ecdsa.PublicKey: 260 key1 := key1Iface.(*ecdsa.PublicKey) 261 key2, ok := key2Iface.(*ecdsa.PublicKey) 262 if !ok { 263 return false, fmt.Errorf("key types do not match: %T and %T", key1Iface, key2Iface) 264 } 265 if key1.X.Cmp(key2.X) != 0 || 266 key1.Y.Cmp(key2.Y) != 0 { 267 return false, nil 268 } 269 key1Params := key1.Params() 270 key2Params := key2.Params() 271 if key1Params.P.Cmp(key2Params.P) != 0 || 272 key1Params.N.Cmp(key2Params.N) != 0 || 273 key1Params.B.Cmp(key2Params.B) != 0 || 274 key1Params.Gx.Cmp(key2Params.Gx) != 0 || 275 key1Params.Gy.Cmp(key2Params.Gy) != 0 || 276 key1Params.BitSize != key2Params.BitSize { 277 return false, nil 278 } 279 return true, nil 280 281 default: 282 return false, fmt.Errorf("cannot compare key with type %T", key1Iface) 283 } 284} 285 286// ParsePublicKeyPEM is used to parse RSA and ECDSA public keys from PEMs 287func ParsePublicKeyPEM(data []byte) (interface{}, error) { 288 block, data := pem.Decode(data) 289 if block != nil { 290 var rawKey interface{} 291 var err error 292 if rawKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { 293 if cert, err := x509.ParseCertificate(block.Bytes); err == nil { 294 rawKey = cert.PublicKey 295 } else { 296 return nil, err 297 } 298 } 299 300 if rsaPublicKey, ok := rawKey.(*rsa.PublicKey); ok { 301 return rsaPublicKey, nil 302 } 303 if ecPublicKey, ok := rawKey.(*ecdsa.PublicKey); ok { 304 return ecPublicKey, nil 305 } 306 } 307 308 return nil, errors.New("data does not contain any valid RSA or ECDSA public keys") 309} 310 311// addPolicyIdentifiers adds certificate policies extension 312// 313func AddPolicyIdentifiers(data *CreationBundle, certTemplate *x509.Certificate) { 314 for _, oidstr := range data.Params.PolicyIdentifiers { 315 oid, err := StringToOid(oidstr) 316 if err == nil { 317 certTemplate.PolicyIdentifiers = append(certTemplate.PolicyIdentifiers, oid) 318 } 319 } 320} 321 322// addExtKeyUsageOids adds custom extended key usage OIDs to certificate 323func AddExtKeyUsageOids(data *CreationBundle, certTemplate *x509.Certificate) { 324 for _, oidstr := range data.Params.ExtKeyUsageOIDs { 325 oid, err := StringToOid(oidstr) 326 if err == nil { 327 certTemplate.UnknownExtKeyUsage = append(certTemplate.UnknownExtKeyUsage, oid) 328 } 329 } 330} 331 332func HandleOtherCSRSANs(in *x509.CertificateRequest, sans map[string][]string) error { 333 certTemplate := &x509.Certificate{ 334 DNSNames: in.DNSNames, 335 IPAddresses: in.IPAddresses, 336 EmailAddresses: in.EmailAddresses, 337 URIs: in.URIs, 338 } 339 if err := HandleOtherSANs(certTemplate, sans); err != nil { 340 return err 341 } 342 if len(certTemplate.ExtraExtensions) > 0 { 343 for _, v := range certTemplate.ExtraExtensions { 344 in.ExtraExtensions = append(in.ExtraExtensions, v) 345 } 346 } 347 return nil 348} 349 350func HandleOtherSANs(in *x509.Certificate, sans map[string][]string) error { 351 // If other SANs is empty we return which causes normal Go stdlib parsing 352 // of the other SAN types 353 if len(sans) == 0 { 354 return nil 355 } 356 357 var rawValues []asn1.RawValue 358 359 // We need to generate an IMPLICIT sequence for compatibility with OpenSSL 360 // -- it's an open question what the default for RFC 5280 actually is, see 361 // https://github.com/openssl/openssl/issues/5091 -- so we have to use 362 // cryptobyte because using the asn1 package's marshaling always produces 363 // an EXPLICIT sequence. Note that asn1 is way too magical according to 364 // agl, and cryptobyte is modeled after the CBB/CBS bits that agl put into 365 // boringssl. 366 for oid, vals := range sans { 367 for _, val := range vals { 368 var b cryptobyte.Builder 369 oidStr, err := StringToOid(oid) 370 if err != nil { 371 return err 372 } 373 b.AddASN1ObjectIdentifier(oidStr) 374 b.AddASN1(cbasn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) { 375 b.AddASN1(cbasn1.UTF8String, func(b *cryptobyte.Builder) { 376 b.AddBytes([]byte(val)) 377 }) 378 }) 379 m, err := b.Bytes() 380 if err != nil { 381 return err 382 } 383 rawValues = append(rawValues, asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: m}) 384 } 385 } 386 387 // If other SANs is empty we return which causes normal Go stdlib parsing 388 // of the other SAN types 389 if len(rawValues) == 0 { 390 return nil 391 } 392 393 // Append any existing SANs, sans marshalling 394 rawValues = append(rawValues, marshalSANs(in.DNSNames, in.EmailAddresses, in.IPAddresses, in.URIs)...) 395 396 // Marshal and add to ExtraExtensions 397 ext := pkix.Extension{ 398 // This is the defined OID for subjectAltName 399 Id: asn1.ObjectIdentifier{2, 5, 29, 17}, 400 } 401 var err error 402 ext.Value, err = asn1.Marshal(rawValues) 403 if err != nil { 404 return err 405 } 406 in.ExtraExtensions = append(in.ExtraExtensions, ext) 407 408 return nil 409} 410 411// Note: Taken from the Go source code since it's not public, and used in the 412// modified function below (which also uses these consts upstream) 413const ( 414 nameTypeEmail = 1 415 nameTypeDNS = 2 416 nameTypeURI = 6 417 nameTypeIP = 7 418) 419 420// Note: Taken from the Go source code since it's not public, plus changed to not marshal 421// marshalSANs marshals a list of addresses into a the contents of an X.509 422// SubjectAlternativeName extension. 423func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) []asn1.RawValue { 424 var rawValues []asn1.RawValue 425 for _, name := range dnsNames { 426 rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)}) 427 } 428 for _, email := range emailAddresses { 429 rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)}) 430 } 431 for _, rawIP := range ipAddresses { 432 // If possible, we always want to encode IPv4 addresses in 4 bytes. 433 ip := rawIP.To4() 434 if ip == nil { 435 ip = rawIP 436 } 437 rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip}) 438 } 439 for _, uri := range uris { 440 rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uri.String())}) 441 } 442 return rawValues 443} 444 445func StringToOid(in string) (asn1.ObjectIdentifier, error) { 446 split := strings.Split(in, ".") 447 ret := make(asn1.ObjectIdentifier, 0, len(split)) 448 for _, v := range split { 449 i, err := strconv.Atoi(v) 450 if err != nil { 451 return nil, err 452 } 453 ret = append(ret, i) 454 } 455 return asn1.ObjectIdentifier(ret), nil 456} 457 458func ValidateKeyTypeLength(keyType string, keyBits int) error { 459 switch keyType { 460 case "rsa": 461 switch keyBits { 462 case 2048: 463 case 4096: 464 case 8192: 465 default: 466 return fmt.Errorf("unsupported bit length for RSA key: %d", keyBits) 467 } 468 case "ec": 469 switch keyBits { 470 case 224: 471 case 256: 472 case 384: 473 case 521: 474 default: 475 return fmt.Errorf("unsupported bit length for EC key: %d", keyBits) 476 } 477 case "any": 478 default: 479 return fmt.Errorf("unknown key type %s", keyType) 480 } 481 482 return nil 483} 484 485// Performs the heavy lifting of creating a certificate. Returns 486// a fully-filled-in ParsedCertBundle. 487func CreateCertificate(data *CreationBundle) (*ParsedCertBundle, error) { 488 var err error 489 result := &ParsedCertBundle{} 490 491 serialNumber, err := GenerateSerialNumber() 492 if err != nil { 493 return nil, err 494 } 495 496 if err := GeneratePrivateKey(data.Params.KeyType, 497 data.Params.KeyBits, 498 result); err != nil { 499 return nil, err 500 } 501 502 subjKeyID, err := GetSubjKeyID(result.PrivateKey) 503 if err != nil { 504 return nil, errutil.InternalError{Err: fmt.Sprintf("error getting subject key ID: %s", err)} 505 } 506 507 certTemplate := &x509.Certificate{ 508 SerialNumber: serialNumber, 509 NotBefore: time.Now().Add(-30 * time.Second), 510 NotAfter: data.Params.NotAfter, 511 IsCA: false, 512 SubjectKeyId: subjKeyID, 513 Subject: data.Params.Subject, 514 DNSNames: data.Params.DNSNames, 515 EmailAddresses: data.Params.EmailAddresses, 516 IPAddresses: data.Params.IPAddresses, 517 URIs: data.Params.URIs, 518 } 519 if data.Params.NotBeforeDuration > 0 { 520 certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration) 521 } 522 523 if err := HandleOtherSANs(certTemplate, data.Params.OtherSANs); err != nil { 524 return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()} 525 } 526 527 // Add this before calling addKeyUsages 528 if data.SigningBundle == nil { 529 certTemplate.IsCA = true 530 } else if data.Params.BasicConstraintsValidForNonCA { 531 certTemplate.BasicConstraintsValid = true 532 certTemplate.IsCA = false 533 } 534 535 // This will only be filled in from the generation paths 536 if len(data.Params.PermittedDNSDomains) > 0 { 537 certTemplate.PermittedDNSDomains = data.Params.PermittedDNSDomains 538 certTemplate.PermittedDNSDomainsCritical = true 539 } 540 541 AddPolicyIdentifiers(data, certTemplate) 542 543 AddKeyUsages(data, certTemplate) 544 545 AddExtKeyUsageOids(data, certTemplate) 546 547 certTemplate.IssuingCertificateURL = data.Params.URLs.IssuingCertificates 548 certTemplate.CRLDistributionPoints = data.Params.URLs.CRLDistributionPoints 549 certTemplate.OCSPServer = data.Params.URLs.OCSPServers 550 551 var certBytes []byte 552 if data.SigningBundle != nil { 553 switch data.SigningBundle.PrivateKeyType { 554 case RSAPrivateKey: 555 certTemplate.SignatureAlgorithm = x509.SHA256WithRSA 556 case ECPrivateKey: 557 certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 558 } 559 560 caCert := data.SigningBundle.Certificate 561 certTemplate.AuthorityKeyId = caCert.SubjectKeyId 562 563 certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), data.SigningBundle.PrivateKey) 564 } else { 565 // Creating a self-signed root 566 if data.Params.MaxPathLength == 0 { 567 certTemplate.MaxPathLen = 0 568 certTemplate.MaxPathLenZero = true 569 } else { 570 certTemplate.MaxPathLen = data.Params.MaxPathLength 571 } 572 573 switch data.Params.KeyType { 574 case "rsa": 575 certTemplate.SignatureAlgorithm = x509.SHA256WithRSA 576 case "ec": 577 certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 578 } 579 580 certTemplate.AuthorityKeyId = subjKeyID 581 certTemplate.BasicConstraintsValid = true 582 certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey) 583 } 584 585 if err != nil { 586 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} 587 } 588 589 result.CertificateBytes = certBytes 590 result.Certificate, err = x509.ParseCertificate(certBytes) 591 if err != nil { 592 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} 593 } 594 595 if data.SigningBundle != nil { 596 if len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 && 597 !bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId) { 598 599 result.CAChain = []*CertBlock{ 600 &CertBlock{ 601 Certificate: data.SigningBundle.Certificate, 602 Bytes: data.SigningBundle.CertificateBytes, 603 }, 604 } 605 result.CAChain = append(result.CAChain, data.SigningBundle.CAChain...) 606 } 607 } 608 609 return result, nil 610} 611 612var oidExtensionBasicConstraints = []int{2, 5, 29, 19} 613 614// Creates a CSR. This is currently only meant for use when 615// generating an intermediate certificate. 616func CreateCSR(data *CreationBundle, addBasicConstraints bool) (*ParsedCSRBundle, error) { 617 var err error 618 result := &ParsedCSRBundle{} 619 620 if err := GeneratePrivateKey(data.Params.KeyType, 621 data.Params.KeyBits, 622 result); err != nil { 623 return nil, err 624 } 625 626 // Like many root CAs, other information is ignored 627 csrTemplate := &x509.CertificateRequest{ 628 Subject: data.Params.Subject, 629 DNSNames: data.Params.DNSNames, 630 EmailAddresses: data.Params.EmailAddresses, 631 IPAddresses: data.Params.IPAddresses, 632 URIs: data.Params.URIs, 633 } 634 635 if err := HandleOtherCSRSANs(csrTemplate, data.Params.OtherSANs); err != nil { 636 return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()} 637 } 638 639 if addBasicConstraints { 640 type basicConstraints struct { 641 IsCA bool `asn1:"optional"` 642 MaxPathLen int `asn1:"optional,default:-1"` 643 } 644 val, err := asn1.Marshal(basicConstraints{IsCA: true, MaxPathLen: -1}) 645 if err != nil { 646 return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling basic constraints: {{err}}", err).Error()} 647 } 648 ext := pkix.Extension{ 649 Id: oidExtensionBasicConstraints, 650 Value: val, 651 Critical: true, 652 } 653 csrTemplate.ExtraExtensions = append(csrTemplate.ExtraExtensions, ext) 654 } 655 656 switch data.Params.KeyType { 657 case "rsa": 658 csrTemplate.SignatureAlgorithm = x509.SHA256WithRSA 659 case "ec": 660 csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 661 } 662 663 csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, result.PrivateKey) 664 if err != nil { 665 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} 666 } 667 668 result.CSRBytes = csr 669 result.CSR, err = x509.ParseCertificateRequest(csr) 670 if err != nil { 671 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %v", err)} 672 } 673 674 return result, nil 675} 676 677// Performs the heavy lifting of generating a certificate from a CSR. 678// Returns a ParsedCertBundle sans private keys. 679func SignCertificate(data *CreationBundle) (*ParsedCertBundle, error) { 680 switch { 681 case data == nil: 682 return nil, errutil.UserError{Err: "nil data bundle given to signCertificate"} 683 case data.Params == nil: 684 return nil, errutil.UserError{Err: "nil parameters given to signCertificate"} 685 case data.SigningBundle == nil: 686 return nil, errutil.UserError{Err: "nil signing bundle given to signCertificate"} 687 case data.CSR == nil: 688 return nil, errutil.UserError{Err: "nil csr given to signCertificate"} 689 } 690 691 err := data.CSR.CheckSignature() 692 if err != nil { 693 return nil, errutil.UserError{Err: "request signature invalid"} 694 } 695 696 result := &ParsedCertBundle{} 697 698 serialNumber, err := GenerateSerialNumber() 699 if err != nil { 700 return nil, err 701 } 702 703 marshaledKey, err := x509.MarshalPKIXPublicKey(data.CSR.PublicKey) 704 if err != nil { 705 return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} 706 } 707 subjKeyID := sha1.Sum(marshaledKey) 708 709 caCert := data.SigningBundle.Certificate 710 711 certTemplate := &x509.Certificate{ 712 SerialNumber: serialNumber, 713 Subject: data.Params.Subject, 714 NotBefore: time.Now().Add(-30 * time.Second), 715 NotAfter: data.Params.NotAfter, 716 SubjectKeyId: subjKeyID[:], 717 AuthorityKeyId: caCert.SubjectKeyId, 718 } 719 if data.Params.NotBeforeDuration > 0 { 720 certTemplate.NotBefore = time.Now().Add(-1 * data.Params.NotBeforeDuration) 721 } 722 723 switch data.SigningBundle.PrivateKeyType { 724 case RSAPrivateKey: 725 certTemplate.SignatureAlgorithm = x509.SHA256WithRSA 726 case ECPrivateKey: 727 certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 728 } 729 730 if data.Params.UseCSRValues { 731 certTemplate.Subject = data.CSR.Subject 732 certTemplate.Subject.ExtraNames = certTemplate.Subject.Names 733 734 certTemplate.DNSNames = data.CSR.DNSNames 735 certTemplate.EmailAddresses = data.CSR.EmailAddresses 736 certTemplate.IPAddresses = data.CSR.IPAddresses 737 certTemplate.URIs = data.CSR.URIs 738 739 for _, name := range data.CSR.Extensions { 740 if !name.Id.Equal(oidExtensionBasicConstraints) { 741 certTemplate.ExtraExtensions = append(certTemplate.ExtraExtensions, name) 742 } 743 } 744 745 } else { 746 certTemplate.DNSNames = data.Params.DNSNames 747 certTemplate.EmailAddresses = data.Params.EmailAddresses 748 certTemplate.IPAddresses = data.Params.IPAddresses 749 certTemplate.URIs = data.Params.URIs 750 } 751 752 if err := HandleOtherSANs(certTemplate, data.Params.OtherSANs); err != nil { 753 return nil, errutil.InternalError{Err: errwrap.Wrapf("error marshaling other SANs: {{err}}", err).Error()} 754 } 755 756 AddPolicyIdentifiers(data, certTemplate) 757 758 AddKeyUsages(data, certTemplate) 759 760 AddExtKeyUsageOids(data, certTemplate) 761 762 var certBytes []byte 763 764 certTemplate.IssuingCertificateURL = data.Params.URLs.IssuingCertificates 765 certTemplate.CRLDistributionPoints = data.Params.URLs.CRLDistributionPoints 766 certTemplate.OCSPServer = data.SigningBundle.URLs.OCSPServers 767 768 if data.Params.IsCA { 769 certTemplate.BasicConstraintsValid = true 770 certTemplate.IsCA = true 771 772 if data.SigningBundle.Certificate.MaxPathLen == 0 && 773 data.SigningBundle.Certificate.MaxPathLenZero { 774 return nil, errutil.UserError{Err: "signing certificate has a max path length of zero, and cannot issue further CA certificates"} 775 } 776 777 certTemplate.MaxPathLen = data.Params.MaxPathLength 778 if certTemplate.MaxPathLen == 0 { 779 certTemplate.MaxPathLenZero = true 780 } 781 } else if data.Params.BasicConstraintsValidForNonCA { 782 certTemplate.BasicConstraintsValid = true 783 certTemplate.IsCA = false 784 } 785 786 if len(data.Params.PermittedDNSDomains) > 0 { 787 certTemplate.PermittedDNSDomains = data.Params.PermittedDNSDomains 788 certTemplate.PermittedDNSDomainsCritical = true 789 } 790 791 certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, data.CSR.PublicKey, data.SigningBundle.PrivateKey) 792 793 if err != nil { 794 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} 795 } 796 797 result.CertificateBytes = certBytes 798 result.Certificate, err = x509.ParseCertificate(certBytes) 799 if err != nil { 800 return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} 801 } 802 803 result.CAChain = data.SigningBundle.GetCAChain() 804 805 return result, nil 806} 807