github.com/hashicorp/vault/sdk@v0.11.0/helper/certutil/certutil_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package certutil 5 6 import ( 7 "bytes" 8 "crypto" 9 "crypto/ecdsa" 10 "crypto/ed25519" 11 "crypto/elliptic" 12 "crypto/rand" 13 "crypto/rsa" 14 "crypto/x509" 15 "crypto/x509/pkix" 16 "encoding/asn1" 17 "encoding/json" 18 "encoding/pem" 19 "fmt" 20 "math/big" 21 mathrand "math/rand" 22 "reflect" 23 "strings" 24 "sync" 25 "testing" 26 "time" 27 28 "github.com/fatih/structs" 29 ) 30 31 // Tests converting back and forth between a CertBundle and a ParsedCertBundle. 32 // 33 // Also tests the GetSubjKeyID, GetHexFormatted, ParseHexFormatted and 34 // ParsedCertBundle.getSigner functions. 35 func TestCertBundleConversion(t *testing.T) { 36 cbuts := []*CertBundle{ 37 refreshRSACertBundle(), 38 refreshRSACertBundleWithChain(), 39 refreshRSA8CertBundle(), 40 refreshRSA8CertBundleWithChain(), 41 refreshECCertBundle(), 42 refreshECCertBundleWithChain(), 43 refreshEC8CertBundle(), 44 refreshEC8CertBundleWithChain(), 45 refreshEd255198CertBundle(), 46 refreshEd255198CertBundleWithChain(), 47 } 48 49 for i, cbut := range cbuts { 50 pcbut, err := cbut.ToParsedCertBundle() 51 if err != nil { 52 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 53 t.Errorf("Error converting to parsed cert bundle: %s", err) 54 continue 55 } 56 57 err = compareCertBundleToParsedCertBundle(cbut, pcbut) 58 if err != nil { 59 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 60 t.Errorf(err.Error()) 61 } 62 63 cbut, err := pcbut.ToCertBundle() 64 if err != nil { 65 t.Fatalf("Error converting to cert bundle: %s", err) 66 } 67 68 err = compareCertBundleToParsedCertBundle(cbut, pcbut) 69 if err != nil { 70 t.Fatalf(err.Error()) 71 } 72 } 73 } 74 75 func BenchmarkCertBundleParsing(b *testing.B) { 76 for i := 0; i < b.N; i++ { 77 cbuts := []*CertBundle{ 78 refreshRSACertBundle(), 79 refreshRSACertBundleWithChain(), 80 refreshRSA8CertBundle(), 81 refreshRSA8CertBundleWithChain(), 82 refreshECCertBundle(), 83 refreshECCertBundleWithChain(), 84 refreshEC8CertBundle(), 85 refreshEC8CertBundleWithChain(), 86 refreshEd255198CertBundle(), 87 refreshEd255198CertBundleWithChain(), 88 } 89 90 for i, cbut := range cbuts { 91 pcbut, err := cbut.ToParsedCertBundle() 92 if err != nil { 93 b.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 94 b.Errorf("Error converting to parsed cert bundle: %s", err) 95 continue 96 } 97 98 cbut, err = pcbut.ToCertBundle() 99 if err != nil { 100 b.Fatalf("Error converting to cert bundle: %s", err) 101 } 102 } 103 } 104 } 105 106 func TestCertBundleParsing(t *testing.T) { 107 cbuts := []*CertBundle{ 108 refreshRSACertBundle(), 109 refreshRSACertBundleWithChain(), 110 refreshRSA8CertBundle(), 111 refreshRSA8CertBundleWithChain(), 112 refreshECCertBundle(), 113 refreshECCertBundleWithChain(), 114 refreshEC8CertBundle(), 115 refreshEC8CertBundleWithChain(), 116 refreshEd255198CertBundle(), 117 refreshEd255198CertBundleWithChain(), 118 } 119 120 for i, cbut := range cbuts { 121 jsonString, err := json.Marshal(cbut) 122 if err != nil { 123 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 124 t.Fatalf("Error marshaling testing certbundle to JSON: %s", err) 125 } 126 pcbut, err := ParsePKIJSON(jsonString) 127 if err != nil { 128 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 129 t.Fatalf("Error during JSON bundle handling: %s", err) 130 } 131 err = compareCertBundleToParsedCertBundle(cbut, pcbut) 132 if err != nil { 133 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 134 t.Fatalf(err.Error()) 135 } 136 137 dataMap := structs.New(cbut).Map() 138 pcbut, err = ParsePKIMap(dataMap) 139 if err != nil { 140 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 141 t.Fatalf("Error during JSON bundle handling: %s", err) 142 } 143 err = compareCertBundleToParsedCertBundle(cbut, pcbut) 144 if err != nil { 145 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 146 t.Fatalf(err.Error()) 147 } 148 149 pcbut, err = ParsePEMBundle(cbut.ToPEMBundle()) 150 if err != nil { 151 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 152 t.Fatalf("Error during JSON bundle handling: %s", err) 153 } 154 err = compareCertBundleToParsedCertBundle(cbut, pcbut) 155 if err != nil { 156 t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i) 157 t.Fatalf(err.Error()) 158 } 159 } 160 } 161 162 func compareCertBundleToParsedCertBundle(cbut *CertBundle, pcbut *ParsedCertBundle) error { 163 if cbut == nil { 164 return fmt.Errorf("got nil bundle") 165 } 166 if pcbut == nil { 167 return fmt.Errorf("got nil parsed bundle") 168 } 169 170 switch { 171 case pcbut.Certificate == nil: 172 return fmt.Errorf("parsed bundle has nil certificate") 173 case pcbut.PrivateKey == nil: 174 return fmt.Errorf("parsed bundle has nil private key") 175 } 176 177 switch cbut.PrivateKey { 178 case privRSAKeyPem: 179 if pcbut.PrivateKeyType != RSAPrivateKey { 180 return fmt.Errorf("parsed bundle has wrong private key type: %v, should be 'rsa' (%v)", pcbut.PrivateKeyType, RSAPrivateKey) 181 } 182 case privRSA8KeyPem: 183 if pcbut.PrivateKeyType != RSAPrivateKey { 184 return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'rsa' (%v)", pcbut.PrivateKeyType, RSAPrivateKey) 185 } 186 case privECKeyPem: 187 if pcbut.PrivateKeyType != ECPrivateKey { 188 return fmt.Errorf("parsed bundle has wrong private key type: %v, should be 'ec' (%v)", pcbut.PrivateKeyType, ECPrivateKey) 189 } 190 case privEC8KeyPem: 191 if pcbut.PrivateKeyType != ECPrivateKey { 192 return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ec' (%v)", pcbut.PrivateKeyType, ECPrivateKey) 193 } 194 case privEd255198KeyPem: 195 if pcbut.PrivateKeyType != Ed25519PrivateKey { 196 return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ed25519' (%v)", pcbut.PrivateKeyType, ECPrivateKey) 197 } 198 default: 199 return fmt.Errorf("parsed bundle has unknown private key type") 200 } 201 202 subjKeyID, err := GetSubjKeyID(pcbut.PrivateKey) 203 if err != nil { 204 return fmt.Errorf("error when getting subject key id: %s", err) 205 } 206 if bytes.Compare(subjKeyID, pcbut.Certificate.SubjectKeyId) != 0 { 207 return fmt.Errorf("parsed bundle private key does not match subject key id\nGot\n%#v\nExpected\n%#v\nCert\n%#v", subjKeyID, pcbut.Certificate.SubjectKeyId, *pcbut.Certificate) 208 } 209 210 switch { 211 case len(pcbut.CAChain) > 0 && len(cbut.CAChain) == 0: 212 return fmt.Errorf("parsed bundle ca chain has certs when cert bundle does not") 213 case len(pcbut.CAChain) == 0 && len(cbut.CAChain) > 0: 214 return fmt.Errorf("cert bundle ca chain has certs when parsed cert bundle does not") 215 } 216 217 cb, err := pcbut.ToCertBundle() 218 if err != nil { 219 return fmt.Errorf("thrown error during parsed bundle conversion: %s\n\nInput was: %#v", err, *pcbut) 220 } 221 222 switch { 223 case len(cb.Certificate) == 0: 224 return fmt.Errorf("bundle has nil certificate") 225 case len(cb.PrivateKey) == 0: 226 return fmt.Errorf("bundle has nil private key") 227 case len(cb.CAChain[0]) == 0: 228 return fmt.Errorf("bundle has nil issuing CA") 229 } 230 231 switch pcbut.PrivateKeyType { 232 case RSAPrivateKey: 233 if cb.PrivateKey != privRSAKeyPem && cb.PrivateKey != privRSA8KeyPem { 234 return fmt.Errorf("bundle private key does not match") 235 } 236 case ECPrivateKey: 237 if cb.PrivateKey != privECKeyPem && cb.PrivateKey != privEC8KeyPem { 238 return fmt.Errorf("bundle private key does not match") 239 } 240 case Ed25519PrivateKey: 241 if cb.PrivateKey != privEd255198KeyPem { 242 return fmt.Errorf("bundle private key does not match") 243 } 244 default: 245 return fmt.Errorf("certBundle has unknown private key type") 246 } 247 248 if cb.SerialNumber != GetHexFormatted(pcbut.Certificate.SerialNumber.Bytes(), ":") { 249 return fmt.Errorf("bundle serial number does not match") 250 } 251 252 if !bytes.Equal(pcbut.Certificate.SerialNumber.Bytes(), ParseHexFormatted(cb.SerialNumber, ":")) { 253 return fmt.Errorf("failed re-parsing hex formatted number %s", cb.SerialNumber) 254 } 255 256 switch { 257 case len(pcbut.CAChain) > 0 && len(cb.CAChain) == 0: 258 return fmt.Errorf("parsed bundle ca chain has certs when cert bundle does not") 259 case len(pcbut.CAChain) == 0 && len(cb.CAChain) > 0: 260 return fmt.Errorf("cert bundle ca chain has certs when parsed cert bundle does not") 261 case !reflect.DeepEqual(cbut.CAChain, cb.CAChain): 262 return fmt.Errorf("cert bundle ca chain does not match: %#v\n\n%#v", cbut.CAChain, cb.CAChain) 263 } 264 265 return nil 266 } 267 268 func TestCSRBundleConversion(t *testing.T) { 269 csrbuts := []*CSRBundle{ 270 refreshRSACSRBundle(), 271 refreshECCSRBundle(), 272 refreshEd25519CSRBundle(), 273 } 274 275 for _, csrbut := range csrbuts { 276 pcsrbut, err := csrbut.ToParsedCSRBundle() 277 if err != nil { 278 t.Fatalf("Error converting to parsed CSR bundle: %v", err) 279 } 280 281 err = compareCSRBundleToParsedCSRBundle(csrbut, pcsrbut) 282 if err != nil { 283 t.Fatalf(err.Error()) 284 } 285 286 csrbut, err = pcsrbut.ToCSRBundle() 287 if err != nil { 288 t.Fatalf("Error converting to CSR bundle: %v", err) 289 } 290 291 err = compareCSRBundleToParsedCSRBundle(csrbut, pcsrbut) 292 if err != nil { 293 t.Fatalf(err.Error()) 294 } 295 } 296 } 297 298 func compareCSRBundleToParsedCSRBundle(csrbut *CSRBundle, pcsrbut *ParsedCSRBundle) error { 299 if csrbut == nil { 300 return fmt.Errorf("got nil bundle") 301 } 302 if pcsrbut == nil { 303 return fmt.Errorf("got nil parsed bundle") 304 } 305 306 switch { 307 case pcsrbut.CSR == nil: 308 return fmt.Errorf("parsed bundle has nil csr") 309 case pcsrbut.PrivateKey == nil: 310 return fmt.Errorf("parsed bundle has nil private key") 311 } 312 313 switch csrbut.PrivateKey { 314 case privRSAKeyPem: 315 if pcsrbut.PrivateKeyType != RSAPrivateKey { 316 return fmt.Errorf("parsed bundle has wrong private key type") 317 } 318 case privECKeyPem: 319 if pcsrbut.PrivateKeyType != ECPrivateKey { 320 return fmt.Errorf("parsed bundle has wrong private key type") 321 } 322 case privEd255198KeyPem: 323 if pcsrbut.PrivateKeyType != Ed25519PrivateKey { 324 return fmt.Errorf("parsed bundle has wrong private key type") 325 } 326 default: 327 return fmt.Errorf("parsed bundle has unknown private key type") 328 } 329 330 csrb, err := pcsrbut.ToCSRBundle() 331 if err != nil { 332 return fmt.Errorf("Thrown error during parsed bundle conversion: %s\n\nInput was: %#v", err, *pcsrbut) 333 } 334 335 switch { 336 case len(csrb.CSR) == 0: 337 return fmt.Errorf("bundle has nil certificate") 338 case len(csrb.PrivateKey) == 0: 339 return fmt.Errorf("bundle has nil private key") 340 } 341 342 switch csrb.PrivateKeyType { 343 case "rsa": 344 if pcsrbut.PrivateKeyType != RSAPrivateKey { 345 return fmt.Errorf("bundle has wrong private key type") 346 } 347 if csrb.PrivateKey != privRSAKeyPem { 348 return fmt.Errorf("bundle rsa private key does not match\nGot\n%#v\nExpected\n%#v", csrb.PrivateKey, privRSAKeyPem) 349 } 350 case "ec": 351 if pcsrbut.PrivateKeyType != ECPrivateKey { 352 return fmt.Errorf("bundle has wrong private key type") 353 } 354 if csrb.PrivateKey != privECKeyPem { 355 return fmt.Errorf("bundle ec private key does not match") 356 } 357 case "ed25519": 358 if pcsrbut.PrivateKeyType != Ed25519PrivateKey { 359 return fmt.Errorf("bundle has wrong private key type") 360 } 361 if csrb.PrivateKey != privEd255198KeyPem { 362 return fmt.Errorf("bundle ed25519 private key does not match") 363 } 364 default: 365 return fmt.Errorf("bundle has unknown private key type") 366 } 367 368 return nil 369 } 370 371 func TestTLSConfig(t *testing.T) { 372 cbut := refreshRSACertBundle() 373 374 pcbut, err := cbut.ToParsedCertBundle() 375 if err != nil { 376 t.Fatalf("Error getting parsed cert bundle: %s", err) 377 } 378 379 usages := []TLSUsage{ 380 TLSUnknown, 381 TLSClient, 382 TLSServer, 383 TLSClient | TLSServer, 384 } 385 386 for _, usage := range usages { 387 tlsConfig, err := pcbut.GetTLSConfig(usage) 388 if err != nil { 389 t.Fatalf("Error getting tls config: %s", err) 390 } 391 if tlsConfig == nil { 392 t.Fatalf("Got nil tls.Config") 393 } 394 395 if len(tlsConfig.Certificates) != 1 { 396 t.Fatalf("Unexpected length in config.Certificates") 397 } 398 399 // Length should be 2, since we passed in a CA 400 if len(tlsConfig.Certificates[0].Certificate) != 2 { 401 t.Fatalf("Did not find both certificates in config.Certificates.Certificate") 402 } 403 404 if tlsConfig.Certificates[0].Leaf != pcbut.Certificate { 405 t.Fatalf("Leaf certificate does not match parsed bundle's certificate") 406 } 407 408 if tlsConfig.Certificates[0].PrivateKey != pcbut.PrivateKey { 409 t.Fatalf("Config's private key does not match parsed bundle's private key") 410 } 411 412 switch usage { 413 case TLSServer | TLSClient: 414 if len(tlsConfig.ClientCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.ClientCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 { 415 t.Fatalf("CA certificate not in client cert pool as expected") 416 } 417 if len(tlsConfig.RootCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.RootCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 { 418 t.Fatalf("CA certificate not in root cert pool as expected") 419 } 420 case TLSServer: 421 if len(tlsConfig.ClientCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.ClientCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 { 422 t.Fatalf("CA certificate not in client cert pool as expected") 423 } 424 if tlsConfig.RootCAs != nil { 425 t.Fatalf("Found root pools in config object when not expected") 426 } 427 case TLSClient: 428 if len(tlsConfig.RootCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.RootCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 { 429 t.Fatalf("CA certificate not in root cert pool as expected") 430 } 431 if tlsConfig.ClientCAs != nil { 432 t.Fatalf("Found root pools in config object when not expected") 433 } 434 default: 435 if tlsConfig.RootCAs != nil || tlsConfig.ClientCAs != nil { 436 t.Fatalf("Found root pools in config object when not expected") 437 } 438 } 439 } 440 } 441 442 func TestNewCertPool(t *testing.T) { 443 caExample := `-----BEGIN CERTIFICATE----- 444 MIIC5zCCAc+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p 445 a3ViZUNBMB4XDTE5MTIxMDIzMDUxOVoXDTI5MTIwODIzMDUxOVowFTETMBEGA1UE 446 AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFi 447 /RIdMHd865X6JygTb9riX01DA3QnR+RoXDXNnj8D3LziLG2n8ItXMJvWbU3sxxyy 448 nX9HxJ0SIeexj1cYzdQBtJDjO1/PeuKc4CZ7zCukCAtHz8mC7BDPOU7F7pggpcQ0 449 /t/pa2m22hmCu8aDF9WlUYHtJpYATnI/A5vz/VFLR9daxmkl59Qo3oHITj7vAzSx 450 /75r9cibpQyJ+FhiHOZHQWYY2JYw2g4v5hm5hg5SFM9yFcZ75ISI9ebyFFIl9iBY 451 zAk9jqv1mXvLr0Q39AVwMTamvGuap1oocjM9NIhQvaFL/DNqF1ouDQjCf5u2imLc 452 TraO1/2KO8fqwOZCOrMCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW 453 MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 454 DQEBCwUAA4IBAQBtVZCwCPqUUUpIClAlE9nc2fo2bTs9gsjXRmqdQ5oaSomSLE93 455 aJWYFuAhxPXtlApbLYZfW2m1sM3mTVQN60y0uE4e1jdSN1ErYQ9slJdYDAMaEmOh 456 iSexj+Nd1scUiMHV9lf3ps5J8sYeCpwZX3sPmw7lqZojTS12pANBDcigsaj5RRyN 457 9GyP3WkSQUsTpWlDb9Fd+KNdkCVw7nClIpBPA2KW4BQKw/rNSvOFD61mbzc89lo0 458 Q9IFGQFFF8jO18lbyWqnRBGXcS4/G7jQ3S7C121d14YLUeAYOM7pJykI1g4CLx9y 459 vitin0L6nprauWkKO38XgM4T75qKZpqtiOcT 460 -----END CERTIFICATE----- 461 ` 462 if _, err := NewCertPool(bytes.NewReader([]byte(caExample))); err != nil { 463 t.Fatal(err) 464 } 465 } 466 467 func TestGetPublicKeySize(t *testing.T) { 468 rsa, err := rsa.GenerateKey(rand.Reader, 3072) 469 if err != nil { 470 t.Fatal(err) 471 } 472 if GetPublicKeySize(&rsa.PublicKey) != 3072 { 473 t.Fatal("unexpected rsa key size") 474 } 475 ecdsa, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 476 if err != nil { 477 t.Fatal(err) 478 } 479 if GetPublicKeySize(&ecdsa.PublicKey) != 384 { 480 t.Fatal("unexpected ecdsa key size") 481 } 482 ed25519, _, err := ed25519.GenerateKey(rand.Reader) 483 if err != nil { 484 t.Fatal(err) 485 } 486 if GetPublicKeySize(ed25519) != 256 { 487 t.Fatal("unexpected ed25519 key size") 488 } 489 // Skipping DSA as too slow 490 } 491 492 func refreshRSA8CertBundle() *CertBundle { 493 initTest.Do(setCerts) 494 return &CertBundle{ 495 Certificate: certRSAPem, 496 PrivateKey: privRSA8KeyPem, 497 CAChain: []string{issuingCaChainPem[0]}, 498 } 499 } 500 501 func refreshRSA8CertBundleWithChain() *CertBundle { 502 initTest.Do(setCerts) 503 ret := refreshRSA8CertBundle() 504 ret.CAChain = issuingCaChainPem 505 return ret 506 } 507 508 func refreshRSACertBundle() *CertBundle { 509 initTest.Do(setCerts) 510 return &CertBundle{ 511 Certificate: certRSAPem, 512 CAChain: []string{issuingCaChainPem[0]}, 513 PrivateKey: privRSAKeyPem, 514 } 515 } 516 517 func refreshRSACertBundleWithChain() *CertBundle { 518 initTest.Do(setCerts) 519 ret := refreshRSACertBundle() 520 ret.CAChain = issuingCaChainPem 521 return ret 522 } 523 524 func refreshECCertBundle() *CertBundle { 525 initTest.Do(setCerts) 526 return &CertBundle{ 527 Certificate: certECPem, 528 CAChain: []string{issuingCaChainPem[0]}, 529 PrivateKey: privECKeyPem, 530 } 531 } 532 533 func refreshECCertBundleWithChain() *CertBundle { 534 initTest.Do(setCerts) 535 ret := refreshECCertBundle() 536 ret.CAChain = issuingCaChainPem 537 return ret 538 } 539 540 func refreshEd255198CertBundle() *CertBundle { 541 initTest.Do(setCerts) 542 return &CertBundle{ 543 Certificate: certEd25519Pem, 544 PrivateKey: privEd255198KeyPem, 545 CAChain: []string{issuingCaChainPem[0]}, 546 } 547 } 548 549 func refreshEd255198CertBundleWithChain() *CertBundle { 550 initTest.Do(setCerts) 551 ret := refreshEd255198CertBundle() 552 ret.CAChain = issuingCaChainPem 553 return ret 554 } 555 556 func refreshEd25519CSRBundle() *CSRBundle { 557 initTest.Do(setCerts) 558 return &CSRBundle{ 559 CSR: csrEd25519Pem, 560 PrivateKey: privEd255198KeyPem, 561 } 562 } 563 564 func refreshRSACSRBundle() *CSRBundle { 565 initTest.Do(setCerts) 566 return &CSRBundle{ 567 CSR: csrRSAPem, 568 PrivateKey: privRSAKeyPem, 569 } 570 } 571 572 func refreshECCSRBundle() *CSRBundle { 573 initTest.Do(setCerts) 574 return &CSRBundle{ 575 CSR: csrECPem, 576 PrivateKey: privECKeyPem, 577 } 578 } 579 580 func refreshEC8CertBundle() *CertBundle { 581 initTest.Do(setCerts) 582 return &CertBundle{ 583 Certificate: certECPem, 584 PrivateKey: privEC8KeyPem, 585 CAChain: []string{issuingCaChainPem[0]}, 586 } 587 } 588 589 func refreshEC8CertBundleWithChain() *CertBundle { 590 initTest.Do(setCerts) 591 ret := refreshEC8CertBundle() 592 ret.CAChain = issuingCaChainPem 593 return ret 594 } 595 596 func setCerts() { 597 caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 598 if err != nil { 599 panic(err) 600 } 601 subjKeyID, err := GetSubjKeyID(caKey) 602 if err != nil { 603 panic(err) 604 } 605 caCertTemplate := &x509.Certificate{ 606 Subject: pkix.Name{ 607 CommonName: "root.localhost", 608 }, 609 SubjectKeyId: subjKeyID, 610 DNSNames: []string{"root.localhost"}, 611 KeyUsage: x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign), 612 SerialNumber: big.NewInt(mathrand.Int63()), 613 NotBefore: time.Now().Add(-30 * time.Second), 614 NotAfter: time.Now().Add(262980 * time.Hour), 615 BasicConstraintsValid: true, 616 IsCA: true, 617 } 618 caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey) 619 if err != nil { 620 panic(err) 621 } 622 caCert, err := x509.ParseCertificate(caBytes) 623 if err != nil { 624 panic(err) 625 } 626 caCertPEMBlock := &pem.Block{ 627 Type: "CERTIFICATE", 628 Bytes: caBytes, 629 } 630 caCertPEM := strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock))) 631 632 intKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 633 if err != nil { 634 panic(err) 635 } 636 subjKeyID, err = GetSubjKeyID(intKey) 637 if err != nil { 638 panic(err) 639 } 640 intCertTemplate := &x509.Certificate{ 641 Subject: pkix.Name{ 642 CommonName: "int.localhost", 643 }, 644 SubjectKeyId: subjKeyID, 645 DNSNames: []string{"int.localhost"}, 646 KeyUsage: x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign), 647 SerialNumber: big.NewInt(mathrand.Int63()), 648 NotBefore: time.Now().Add(-30 * time.Second), 649 NotAfter: time.Now().Add(262980 * time.Hour), 650 BasicConstraintsValid: true, 651 IsCA: true, 652 } 653 intBytes, err := x509.CreateCertificate(rand.Reader, intCertTemplate, caCert, intKey.Public(), caKey) 654 if err != nil { 655 panic(err) 656 } 657 intCert, err := x509.ParseCertificate(intBytes) 658 if err != nil { 659 panic(err) 660 } 661 intCertPEMBlock := &pem.Block{ 662 Type: "CERTIFICATE", 663 Bytes: intBytes, 664 } 665 intCertPEM := strings.TrimSpace(string(pem.EncodeToMemory(intCertPEMBlock))) 666 667 // EC generation 668 { 669 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 670 if err != nil { 671 panic(err) 672 } 673 subjKeyID, err := GetSubjKeyID(key) 674 if err != nil { 675 panic(err) 676 } 677 certTemplate := &x509.Certificate{ 678 Subject: pkix.Name{ 679 CommonName: "localhost", 680 }, 681 SubjectKeyId: subjKeyID, 682 DNSNames: []string{"localhost"}, 683 ExtKeyUsage: []x509.ExtKeyUsage{ 684 x509.ExtKeyUsageServerAuth, 685 x509.ExtKeyUsageClientAuth, 686 }, 687 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 688 SerialNumber: big.NewInt(mathrand.Int63()), 689 NotBefore: time.Now().Add(-30 * time.Second), 690 NotAfter: time.Now().Add(262980 * time.Hour), 691 } 692 csrTemplate := &x509.CertificateRequest{ 693 Subject: pkix.Name{ 694 CommonName: "localhost", 695 }, 696 DNSNames: []string{"localhost"}, 697 } 698 csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, key) 699 if err != nil { 700 panic(err) 701 } 702 csrPEMBlock := &pem.Block{ 703 Type: "CERTIFICATE REQUEST", 704 Bytes: csrBytes, 705 } 706 csrECPem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock))) 707 certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, key.Public(), intKey) 708 if err != nil { 709 panic(err) 710 } 711 certPEMBlock := &pem.Block{ 712 Type: "CERTIFICATE", 713 Bytes: certBytes, 714 } 715 certECPem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock))) 716 marshaledKey, err := x509.MarshalECPrivateKey(key) 717 if err != nil { 718 panic(err) 719 } 720 keyPEMBlock := &pem.Block{ 721 Type: "EC PRIVATE KEY", 722 Bytes: marshaledKey, 723 } 724 privECKeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock))) 725 marshaledKey, err = x509.MarshalPKCS8PrivateKey(key) 726 if err != nil { 727 panic(err) 728 } 729 keyPEMBlock = &pem.Block{ 730 Type: "PRIVATE KEY", 731 Bytes: marshaledKey, 732 } 733 privEC8KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock))) 734 } 735 736 // RSA generation 737 { 738 key, err := rsa.GenerateKey(rand.Reader, 2048) 739 if err != nil { 740 panic(err) 741 } 742 subjKeyID, err := GetSubjKeyID(key) 743 if err != nil { 744 panic(err) 745 } 746 certTemplate := &x509.Certificate{ 747 Subject: pkix.Name{ 748 CommonName: "localhost", 749 }, 750 SubjectKeyId: subjKeyID, 751 DNSNames: []string{"localhost"}, 752 ExtKeyUsage: []x509.ExtKeyUsage{ 753 x509.ExtKeyUsageServerAuth, 754 x509.ExtKeyUsageClientAuth, 755 }, 756 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 757 SerialNumber: big.NewInt(mathrand.Int63()), 758 NotBefore: time.Now().Add(-30 * time.Second), 759 NotAfter: time.Now().Add(262980 * time.Hour), 760 } 761 csrTemplate := &x509.CertificateRequest{ 762 Subject: pkix.Name{ 763 CommonName: "localhost", 764 }, 765 DNSNames: []string{"localhost"}, 766 } 767 csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, key) 768 if err != nil { 769 panic(err) 770 } 771 csrPEMBlock := &pem.Block{ 772 Type: "CERTIFICATE REQUEST", 773 Bytes: csrBytes, 774 } 775 csrRSAPem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock))) 776 certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, key.Public(), intKey) 777 if err != nil { 778 panic(err) 779 } 780 certPEMBlock := &pem.Block{ 781 Type: "CERTIFICATE", 782 Bytes: certBytes, 783 } 784 certRSAPem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock))) 785 marshaledKey := x509.MarshalPKCS1PrivateKey(key) 786 keyPEMBlock := &pem.Block{ 787 Type: "RSA PRIVATE KEY", 788 Bytes: marshaledKey, 789 } 790 privRSAKeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock))) 791 marshaledKey, err = x509.MarshalPKCS8PrivateKey(key) 792 if err != nil { 793 panic(err) 794 } 795 keyPEMBlock = &pem.Block{ 796 Type: "PRIVATE KEY", 797 Bytes: marshaledKey, 798 } 799 privRSA8KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock))) 800 } 801 802 // Ed25519 generation 803 { 804 pubkey, privkey, err := ed25519.GenerateKey(rand.Reader) 805 if err != nil { 806 panic(err) 807 } 808 subjKeyID, err := GetSubjKeyID(privkey) 809 if err != nil { 810 panic(err) 811 } 812 certTemplate := &x509.Certificate{ 813 Subject: pkix.Name{ 814 CommonName: "localhost", 815 }, 816 SubjectKeyId: subjKeyID, 817 DNSNames: []string{"localhost"}, 818 ExtKeyUsage: []x509.ExtKeyUsage{ 819 x509.ExtKeyUsageServerAuth, 820 x509.ExtKeyUsageClientAuth, 821 }, 822 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement, 823 SerialNumber: big.NewInt(mathrand.Int63()), 824 NotBefore: time.Now().Add(-30 * time.Second), 825 NotAfter: time.Now().Add(262980 * time.Hour), 826 } 827 csrTemplate := &x509.CertificateRequest{ 828 Subject: pkix.Name{ 829 CommonName: "localhost", 830 }, 831 DNSNames: []string{"localhost"}, 832 } 833 csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, privkey) 834 if err != nil { 835 panic(err) 836 } 837 csrPEMBlock := &pem.Block{ 838 Type: "CERTIFICATE REQUEST", 839 Bytes: csrBytes, 840 } 841 csrEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock))) 842 certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, pubkey, intKey) 843 if err != nil { 844 panic(err) 845 } 846 certPEMBlock := &pem.Block{ 847 Type: "CERTIFICATE", 848 Bytes: certBytes, 849 } 850 certEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock))) 851 marshaledKey, err := x509.MarshalPKCS8PrivateKey(privkey) 852 if err != nil { 853 panic(err) 854 } 855 keyPEMBlock := &pem.Block{ 856 Type: "PRIVATE KEY", 857 Bytes: marshaledKey, 858 } 859 privEd255198KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock))) 860 } 861 862 issuingCaChainPem = []string{intCertPEM, caCertPEM} 863 } 864 865 func TestComparePublicKeysAndType(t *testing.T) { 866 rsa1 := genRsaKey(t).Public() 867 rsa2 := genRsaKey(t).Public() 868 eddsa1 := genEdDSA(t).Public() 869 eddsa2 := genEdDSA(t).Public() 870 ed25519_1, _ := genEd25519Key(t) 871 ed25519_2, _ := genEd25519Key(t) 872 873 type args struct { 874 key1Iface crypto.PublicKey 875 key2Iface crypto.PublicKey 876 } 877 tests := []struct { 878 name string 879 args args 880 want bool 881 wantErr bool 882 }{ 883 {name: "RSA_Equal", args: args{key1Iface: rsa1, key2Iface: rsa1}, want: true, wantErr: false}, 884 {name: "RSA_NotEqual", args: args{key1Iface: rsa1, key2Iface: rsa2}, want: false, wantErr: false}, 885 {name: "EDDSA_Equal", args: args{key1Iface: eddsa1, key2Iface: eddsa1}, want: true, wantErr: false}, 886 {name: "EDDSA_NotEqual", args: args{key1Iface: eddsa1, key2Iface: eddsa2}, want: false, wantErr: false}, 887 {name: "ED25519_Equal", args: args{key1Iface: ed25519_1, key2Iface: ed25519_1}, want: true, wantErr: false}, 888 {name: "ED25519_NotEqual", args: args{key1Iface: ed25519_1, key2Iface: ed25519_2}, want: false, wantErr: false}, 889 {name: "Mismatched_RSA", args: args{key1Iface: rsa1, key2Iface: ed25519_2}, want: false, wantErr: false}, 890 {name: "Mismatched_EDDSA", args: args{key1Iface: ed25519_1, key2Iface: rsa1}, want: false, wantErr: false}, 891 {name: "Mismatched_ED25519", args: args{key1Iface: ed25519_1, key2Iface: rsa1}, want: false, wantErr: false}, 892 } 893 for _, tt := range tests { 894 t.Run(tt.name, func(t *testing.T) { 895 got, err := ComparePublicKeysAndType(tt.args.key1Iface, tt.args.key2Iface) 896 if (err != nil) != tt.wantErr { 897 t.Errorf("ComparePublicKeysAndType() error = %v, wantErr %v", err, tt.wantErr) 898 return 899 } 900 if got != tt.want { 901 t.Errorf("ComparePublicKeysAndType() got = %v, want %v", got, tt.want) 902 } 903 }) 904 } 905 } 906 907 func TestNotAfterValues(t *testing.T) { 908 if ErrNotAfterBehavior != 0 { 909 t.Fatalf("Expected ErrNotAfterBehavior=%v to have value 0", ErrNotAfterBehavior) 910 } 911 912 if TruncateNotAfterBehavior != 1 { 913 t.Fatalf("Expected TruncateNotAfterBehavior=%v to have value 1", TruncateNotAfterBehavior) 914 } 915 916 if PermitNotAfterBehavior != 2 { 917 t.Fatalf("Expected PermitNotAfterBehavior=%v to have value 2", PermitNotAfterBehavior) 918 } 919 } 920 921 func TestSignatureAlgorithmRoundTripping(t *testing.T) { 922 for leftName, value := range SignatureAlgorithmNames { 923 if leftName == "pureed25519" && value == x509.PureEd25519 { 924 continue 925 } 926 927 rightName, present := InvSignatureAlgorithmNames[value] 928 if !present { 929 t.Fatalf("%v=%v is present in SignatureAlgorithmNames but not in InvSignatureAlgorithmNames", leftName, value) 930 } 931 932 if strings.ToLower(rightName) != leftName { 933 t.Fatalf("%v=%v is present in SignatureAlgorithmNames but inverse for %v has different name: %v", leftName, value, value, rightName) 934 } 935 } 936 937 for leftValue, name := range InvSignatureAlgorithmNames { 938 rightValue, present := SignatureAlgorithmNames[strings.ToLower(name)] 939 if !present { 940 t.Fatalf("%v=%v is present in InvSignatureAlgorithmNames but not in SignatureAlgorithmNames", leftValue, name) 941 } 942 943 if rightValue != leftValue { 944 t.Fatalf("%v=%v is present in InvSignatureAlgorithmNames but forwards for %v has different value: %v", leftValue, name, name, rightValue) 945 } 946 } 947 } 948 949 // TestParseBasicConstraintExtension Verify extension generation and parsing of x509 basic constraint extensions 950 // works as expected. 951 func TestBasicConstraintExtension(t *testing.T) { 952 t.Parallel() 953 954 tests := []struct { 955 name string 956 isCA bool 957 maxPathLen int 958 }{ 959 {"empty-seq", false, -1}, 960 {"just-ca-true", true, -1}, 961 {"just-ca-with-maxpathlen", true, 2}, 962 } 963 for _, tt := range tests { 964 t.Run(tt.name, func(t *testing.T) { 965 ext, err := CreateBasicConstraintExtension(tt.isCA, tt.maxPathLen) 966 if err != nil { 967 t.Fatalf("failed generating basic extension: %v", err) 968 } 969 970 gotIsCa, gotMaxPathLen, err := ParseBasicConstraintExtension(ext) 971 if err != nil { 972 t.Fatalf("failed parsing basic extension: %v", err) 973 } 974 975 if tt.isCA != gotIsCa { 976 t.Fatalf("expected isCa (%v) got isCa (%v)", tt.isCA, gotIsCa) 977 } 978 979 if tt.maxPathLen != gotMaxPathLen { 980 t.Fatalf("expected maxPathLen (%v) got maxPathLen (%v)", tt.maxPathLen, gotMaxPathLen) 981 } 982 }) 983 } 984 985 t.Run("bad-extension-oid", func(t *testing.T) { 986 // Test invalid type errors out 987 _, _, err := ParseBasicConstraintExtension(pkix.Extension{}) 988 if err == nil { 989 t.Fatalf("should have failed parsing non-basic constraint extension") 990 } 991 }) 992 993 t.Run("garbage-value", func(t *testing.T) { 994 extraBytes, err := asn1.Marshal("a string") 995 if err != nil { 996 t.Fatalf("failed encoding the struct: %v", err) 997 } 998 ext := pkix.Extension{ 999 Id: ExtensionBasicConstraintsOID, 1000 Value: extraBytes, 1001 } 1002 _, _, err = ParseBasicConstraintExtension(ext) 1003 if err == nil { 1004 t.Fatalf("should have failed parsing basic constraint with extra information") 1005 } 1006 }) 1007 } 1008 1009 func genRsaKey(t *testing.T) *rsa.PrivateKey { 1010 key, err := rsa.GenerateKey(rand.Reader, 2048) 1011 if err != nil { 1012 t.Fatal(err) 1013 } 1014 return key 1015 } 1016 1017 func genEdDSA(t *testing.T) *ecdsa.PrivateKey { 1018 key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 1019 if err != nil { 1020 t.Fatal(err) 1021 } 1022 return key 1023 } 1024 1025 func genEd25519Key(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) { 1026 key, priv, err := ed25519.GenerateKey(rand.Reader) 1027 if err != nil { 1028 t.Fatal(err) 1029 } 1030 return key, priv 1031 } 1032 1033 var ( 1034 initTest sync.Once 1035 privRSA8KeyPem string 1036 privRSAKeyPem string 1037 csrRSAPem string 1038 certRSAPem string 1039 privEd255198KeyPem string 1040 csrEd25519Pem string 1041 certEd25519Pem string 1042 privECKeyPem string 1043 csrECPem string 1044 privEC8KeyPem string 1045 certECPem string 1046 issuingCaChainPem []string 1047 )