ocspstapling_test.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package ocspstapling
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/rand"
  6. "crypto/rsa"
  7. "crypto/x509"
  8. "crypto/x509/pkix"
  9. "encoding/base64"
  10. "math/big"
  11. "os"
  12. "testing"
  13. "github.com/cloudflare/cfssl/certdb"
  14. "github.com/cloudflare/cfssl/certdb/sql"
  15. "github.com/cloudflare/cfssl/certdb/testdb"
  16. "github.com/cloudflare/cfssl/helpers"
  17. "github.com/google/certificate-transparency-go"
  18. "golang.org/x/crypto/ocsp"
  19. )
  20. func TestStapleSCTList(t *testing.T) {
  21. // issuer is a CA certificate.
  22. issuer, issuerPrivKey, err := makeCert(nil)
  23. if err != nil {
  24. t.Fatal(err)
  25. }
  26. // responderCert is a certificate for which to make an OCSP response.
  27. responderCert, _, err := makeCert(issuer)
  28. if err != nil {
  29. t.Fatal(err)
  30. }
  31. template := ocsp.Response{
  32. SerialNumber: responderCert.SerialNumber,
  33. IssuerHash: crypto.SHA256,
  34. Status: ocsp.Good,
  35. }
  36. // respDER is an OCSP response to be added to the database.
  37. respDER, err := ocsp.CreateResponse(issuer, responderCert, template, issuerPrivKey)
  38. if err != nil {
  39. t.Fatal(err)
  40. }
  41. // testDB is an empty DB of OCSP responses.
  42. gopath := os.Getenv("GOPATH")
  43. dbPath := gopath + "/src/github.com/cloudflare/cfssl/certdb/testdb/certstore_development.db"
  44. testDB := sql.NewAccessor(testdb.SQLiteDB(dbPath))
  45. // Next, we store the OCSP response in the DB.
  46. respSN := responderCert.SerialNumber.Text(16)
  47. testDB.InsertOCSP(certdb.OCSPRecord{
  48. Serial: respSN,
  49. Body: base64.StdEncoding.EncodeToString(respDER),
  50. AKI: "Cornell CS 5152",
  51. })
  52. var zeroSCT ct.SignedCertificateTimestamp
  53. err = StapleSCTList(testDB, respSN, "Cornell CS 5152", []ct.SignedCertificateTimestamp{zeroSCT},
  54. responderCert, issuer, issuerPrivKey)
  55. if err != nil {
  56. t.Fatal(err)
  57. }
  58. // Lastly, we verify that the SCT was inserted.
  59. recs, err := testDB.GetOCSP(respSN, "Cornell CS 5152")
  60. if err != nil {
  61. t.Fatal(err)
  62. }
  63. if len(recs) == 0 {
  64. t.Fatal("SCT could not be retrieved from DB:", zeroSCT)
  65. }
  66. respDER, err = base64.StdEncoding.DecodeString(recs[0].Body)
  67. if err != nil {
  68. t.Fatal(err)
  69. }
  70. response, err := ocsp.ParseResponse(respDER, issuer)
  71. if err != nil {
  72. t.Fatal(err)
  73. }
  74. scts, err := helpers.SCTListFromOCSPResponse(response)
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. if len(scts) == 0 {
  79. t.Fatal("No SCTs in OCSP response:", response)
  80. }
  81. // Here, we check the equivalence of the SCT we inserted with the SCT
  82. // returned by SCTListFromOCSPResponse.
  83. // sctEquals returns true if all fields of both SCTs are equivalent.
  84. sctEquals := func(sctA, sctB ct.SignedCertificateTimestamp) bool {
  85. if sctA.SCTVersion == sctB.SCTVersion &&
  86. sctA.LogID == sctB.LogID &&
  87. sctA.Timestamp == sctB.Timestamp &&
  88. bytes.Equal(sctA.Extensions, sctB.Extensions) &&
  89. sctA.Signature.Algorithm == sctB.Signature.Algorithm &&
  90. bytes.Equal(sctA.Signature.Signature, sctA.Signature.Signature) {
  91. return true
  92. }
  93. return false
  94. }
  95. if !sctEquals(scts[0], zeroSCT) {
  96. t.Fatal("SCTs do not match:", "\nGot --", scts[0], "\nExpected --", zeroSCT)
  97. }
  98. }
  99. // serialCounter stores the next serial number to be issued by nextSN.
  100. var serialCounter int64
  101. // nextSN returns a new big.Int for creating x509 certificates.
  102. func nextSN() *big.Int {
  103. i := big.NewInt(serialCounter)
  104. serialCounter++
  105. return i
  106. }
  107. // makeCert returns a new x509 certificate with the given issuer certificate.
  108. // If issuer is nil, the certificate is self-signed.
  109. func makeCert(issuer *x509.Certificate) (*x509.Certificate, crypto.Signer, error) {
  110. // Create a new private key
  111. privKey, err := rsa.GenerateKey(rand.Reader, 1024)
  112. if err != nil {
  113. return nil, nil, err
  114. }
  115. template := x509.Certificate{
  116. SerialNumber: nextSN(),
  117. Subject: pkix.Name{
  118. Organization: []string{"Cornell CS 5152"},
  119. },
  120. AuthorityKeyId: []byte{42, 42, 42, 42},
  121. }
  122. if issuer == nil { // the cert is self-signed
  123. issuer = &template
  124. }
  125. der, err := x509.CreateCertificate(rand.Reader, &template, issuer, privKey.Public(), privKey)
  126. if err != nil {
  127. return nil, nil, err
  128. }
  129. cert, err := x509.ParseCertificate(der)
  130. if err != nil {
  131. return nil, nil, err
  132. }
  133. return cert, privKey, nil
  134. }