bundler_sha1_deprecation_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package bundler
  2. // This test file contains tests on checking Bundle.Status with SHA-1 deprecation warning.
  3. import (
  4. "crypto/x509"
  5. "os"
  6. "testing"
  7. "time"
  8. "github.com/cloudflare/cfssl/config"
  9. "github.com/cloudflare/cfssl/errors"
  10. "github.com/cloudflare/cfssl/helpers"
  11. "github.com/cloudflare/cfssl/signer"
  12. "github.com/cloudflare/cfssl/signer/local"
  13. "github.com/cloudflare/cfssl/ubiquity"
  14. )
  15. const (
  16. sha1CA = "testdata/ca.pem"
  17. sha1CAKey = "testdata/ca.key"
  18. sha1Intermediate = "testdata/inter-L1-sha1.pem"
  19. sha2Intermediate = "testdata/inter-L1.pem"
  20. intermediateKey = "testdata/inter-L1.key"
  21. intermediateCSR = "testdata/inter-L1.csr"
  22. leafCSR = "testdata/cfssl-leaf-ecdsa256.csr"
  23. )
  24. func TestChromeWarning(t *testing.T) {
  25. b := newCustomizedBundlerFromFile(t, sha1CA, sha1Intermediate, "")
  26. s, err := local.NewSignerFromFile(sha1Intermediate, intermediateKey, nil)
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. csrBytes, err := os.ReadFile(leafCSR)
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. signingRequest := signer.SignRequest{Request: string(csrBytes)}
  35. certBytes, err := s.Sign(signingRequest)
  36. if err != nil {
  37. t.Fatal(err)
  38. }
  39. // Bundle a leaf cert with default 1 year expiration
  40. bundle, err := b.BundleFromPEMorDER(certBytes, nil, Ubiquitous, "")
  41. if err != nil {
  42. t.Fatal("bundling failed: ", err)
  43. }
  44. // should be not ubiquitous due to SHA2 and ECDSA support issues in legacy platforms
  45. if bundle.Status.Code&errors.BundleNotUbiquitousBit != errors.BundleNotUbiquitousBit {
  46. t.Fatal("Incorrect bundle status code. Bundle status code:", bundle.Status.Code)
  47. }
  48. fullChain := append(bundle.Chain, bundle.Root)
  49. sha1Msgs := ubiquity.SHA1DeprecationMessages(fullChain)
  50. // Since the new SHA-1 cert is expired after 2015, it definitely trigger Chrome's deprecation policies.
  51. if len(sha1Msgs) == 0 {
  52. t.Fatal("SHA1 Deprecation Message should not be empty")
  53. }
  54. // check SHA1 deprecation warnings
  55. var sha1MsgNotFound bool
  56. for _, sha1Msg := range sha1Msgs {
  57. foundMsg := false
  58. for _, message := range bundle.Status.Messages {
  59. if message == sha1Msg {
  60. foundMsg = true
  61. }
  62. }
  63. if !foundMsg {
  64. sha1MsgNotFound = true
  65. break
  66. }
  67. }
  68. if sha1MsgNotFound {
  69. t.Fatalf("Incorrect bundle status messages. Bundle status messages:%v, expected to contain: %v\n", bundle.Status.Messages, sha1Msgs)
  70. }
  71. }
  72. func TestSHA2Preferences(t *testing.T) {
  73. // create a CA signer and signs a new intermediate with SHA-1
  74. sha1CASigner := makeCASignerFromFile(sha1CA, sha1CAKey, x509.SHA1WithRSA, t)
  75. // create a CA signer and signs a new intermediate with SHA-2
  76. sha2CASigner := makeCASignerFromFile(sha1CA, sha1CAKey, x509.SHA256WithRSA, t)
  77. // sign two different intermediates
  78. sha1InterBytes := signCSRFile(sha1CASigner, intermediateCSR, t)
  79. sha2InterBytes := signCSRFile(sha2CASigner, intermediateCSR, t)
  80. interKeyBytes, err := os.ReadFile(intermediateKey)
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. // create a intermediate signer from SHA-1 intermediate cert/key
  85. sha2InterSigner := makeCASigner(sha1InterBytes, interKeyBytes, x509.SHA256WithRSA, t)
  86. // sign a leaf cert
  87. leafBytes := signCSRFile(sha2InterSigner, leafCSR, t)
  88. // create a bundler with SHA-1 and SHA-2 intermediate certs of same key.
  89. b := newCustomizedBundlerFromFile(t, sha1CA, sha1Intermediate, "")
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. sha1Inter, _ := helpers.ParseCertificatePEM(sha1InterBytes)
  94. sha2Inter, _ := helpers.ParseCertificatePEM(sha2InterBytes)
  95. b.IntermediatePool.AddCert(sha1Inter)
  96. b.IntermediatePool.AddCert(sha2Inter)
  97. bundle, err := b.BundleFromPEMorDER(leafBytes, nil, Ubiquitous, "")
  98. if err != nil {
  99. t.Fatal("bundling failed: ", err)
  100. }
  101. if bundle.Chain[1].SignatureAlgorithm != x509.SHA256WithRSA {
  102. t.Fatal("ubiquity selection by SHA-2 homogenity failed.")
  103. }
  104. }
  105. func makeCASignerFromFile(certFile, keyFile string, sigAlgo x509.SignatureAlgorithm, t *testing.T) signer.Signer {
  106. certBytes, err := os.ReadFile(certFile)
  107. if err != nil {
  108. t.Fatal(err)
  109. }
  110. keyBytes, err := os.ReadFile(keyFile)
  111. if err != nil {
  112. t.Fatal(err)
  113. }
  114. return makeCASigner(certBytes, keyBytes, sigAlgo, t)
  115. }
  116. func makeCASigner(certBytes, keyBytes []byte, sigAlgo x509.SignatureAlgorithm, t *testing.T) signer.Signer {
  117. cert, err := helpers.ParseCertificatePEM(certBytes)
  118. if err != nil {
  119. t.Fatal(err)
  120. }
  121. key, err := helpers.ParsePrivateKeyPEM(keyBytes)
  122. if err != nil {
  123. t.Fatal(err)
  124. }
  125. defaultProfile := &config.SigningProfile{
  126. Usage: []string{"cert sign"},
  127. CAConstraint: config.CAConstraint{IsCA: true},
  128. Expiry: time.Hour,
  129. ExpiryString: "1h",
  130. }
  131. policy := &config.Signing{
  132. Profiles: map[string]*config.SigningProfile{},
  133. Default: defaultProfile,
  134. }
  135. s, err := local.NewSigner(key, cert, sigAlgo, policy)
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. return s
  140. }
  141. func signCSRFile(s signer.Signer, csrFile string, t *testing.T) []byte {
  142. csrBytes, err := os.ReadFile(csrFile)
  143. if err != nil {
  144. t.Fatal(err)
  145. }
  146. signingRequest := signer.SignRequest{Request: string(csrBytes)}
  147. certBytes, err := s.Sign(signingRequest)
  148. if err != nil {
  149. t.Fatal(err)
  150. }
  151. return certBytes
  152. }