crl.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Package crl exposes Certificate Revocation List generation functionality
  2. package crl
  3. import (
  4. "crypto"
  5. "crypto/rand"
  6. "crypto/x509"
  7. "crypto/x509/pkix"
  8. "math/big"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "github.com/cloudflare/cfssl/certdb"
  14. "github.com/cloudflare/cfssl/helpers"
  15. "github.com/cloudflare/cfssl/log"
  16. )
  17. // NewCRLFromFile takes in a list of serial numbers, one per line, as well as the issuing certificate
  18. // of the CRL, and the private key. This function is then used to parse the list and generate a CRL
  19. func NewCRLFromFile(serialList, issuerFile, keyFile []byte, expiryTime string) ([]byte, error) {
  20. var revokedCerts []pkix.RevokedCertificate
  21. var oneWeek = time.Duration(604800) * time.Second
  22. expiryInt, err := strconv.ParseInt(expiryTime, 0, 32)
  23. if err != nil {
  24. return nil, err
  25. }
  26. newDurationFromInt := time.Duration(expiryInt) * time.Second
  27. newExpiryTime := time.Now().Add(newDurationFromInt)
  28. if expiryInt == 0 {
  29. newExpiryTime = time.Now().Add(oneWeek)
  30. }
  31. // Parse the PEM encoded certificate
  32. issuerCert, err := helpers.ParseCertificatePEM(issuerFile)
  33. if err != nil {
  34. return nil, err
  35. }
  36. // Split input file by new lines
  37. individualCerts := strings.Split(string(serialList), "\n")
  38. // For every new line, create a new revokedCertificate and add it to slice
  39. for _, value := range individualCerts {
  40. if len(strings.TrimSpace(value)) == 0 {
  41. continue
  42. }
  43. tempBigInt := new(big.Int)
  44. tempBigInt.SetString(value, 10)
  45. tempCert := pkix.RevokedCertificate{
  46. SerialNumber: tempBigInt,
  47. RevocationTime: time.Now(),
  48. }
  49. revokedCerts = append(revokedCerts, tempCert)
  50. }
  51. strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
  52. password := []byte(strPassword)
  53. if strPassword == "" {
  54. password = nil
  55. }
  56. // Parse the key given
  57. key, err := helpers.ParsePrivateKeyPEMWithPassword(keyFile, password)
  58. if err != nil {
  59. log.Debugf("Malformed private key %v", err)
  60. return nil, err
  61. }
  62. return CreateGenericCRL(revokedCerts, key, issuerCert, newExpiryTime)
  63. }
  64. // NewCRLFromDB takes in a list of CertificateRecords, as well as the issuing certificate
  65. // of the CRL, and the private key. This function is then used to parse the records and generate a CRL
  66. func NewCRLFromDB(certs []certdb.CertificateRecord, issuerCert *x509.Certificate, key crypto.Signer, expiryTime time.Duration) ([]byte, error) {
  67. var revokedCerts []pkix.RevokedCertificate
  68. newExpiryTime := time.Now().Add(expiryTime)
  69. // For every record, create a new revokedCertificate and add it to slice
  70. for _, certRecord := range certs {
  71. serialInt := new(big.Int)
  72. serialInt.SetString(certRecord.Serial, 10)
  73. tempCert := pkix.RevokedCertificate{
  74. SerialNumber: serialInt,
  75. RevocationTime: certRecord.RevokedAt,
  76. }
  77. revokedCerts = append(revokedCerts, tempCert)
  78. }
  79. return CreateGenericCRL(revokedCerts, key, issuerCert, newExpiryTime)
  80. }
  81. // CreateGenericCRL is a helper function that takes in all of the information above, and then calls the createCRL
  82. // function. This outputs the bytes of the created CRL.
  83. func CreateGenericCRL(certList []pkix.RevokedCertificate, key crypto.Signer, issuingCert *x509.Certificate, expiryTime time.Time) ([]byte, error) {
  84. crlBytes, err := issuingCert.CreateCRL(rand.Reader, key, certList, time.Now(), expiryTime)
  85. if err != nil {
  86. log.Debugf("error creating CRL: %s", err)
  87. }
  88. return crlBytes, err
  89. }