initca.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Package initca contains code to initialise a certificate authority,
  2. // generating a new root key and certificate.
  3. package initca
  4. import (
  5. "crypto"
  6. "crypto/ecdsa"
  7. "crypto/rand"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/pem"
  11. "errors"
  12. "time"
  13. "github.com/cloudflare/cfssl/config"
  14. "github.com/cloudflare/cfssl/csr"
  15. cferr "github.com/cloudflare/cfssl/errors"
  16. "github.com/cloudflare/cfssl/helpers"
  17. "github.com/cloudflare/cfssl/log"
  18. "github.com/cloudflare/cfssl/signer"
  19. "github.com/cloudflare/cfssl/signer/local"
  20. )
  21. // validator contains the default validation logic for certificate
  22. // authority certificates. The only requirement here is that the
  23. // certificate have a non-empty subject field.
  24. func validator(req *csr.CertificateRequest) error {
  25. if req.CN != "" {
  26. return nil
  27. }
  28. if len(req.Names) == 0 {
  29. return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
  30. }
  31. for i := range req.Names {
  32. if csr.IsNameEmpty(req.Names[i]) {
  33. return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
  34. }
  35. }
  36. return nil
  37. }
  38. // New creates a new root certificate from the certificate request.
  39. func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
  40. policy := CAPolicy()
  41. if req.CA != nil {
  42. if req.CA.Expiry != "" {
  43. policy.Default.ExpiryString = req.CA.Expiry
  44. policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
  45. if err != nil {
  46. return
  47. }
  48. }
  49. if req.CA.Backdate != "" {
  50. policy.Default.Backdate, err = time.ParseDuration(req.CA.Backdate)
  51. if err != nil {
  52. return
  53. }
  54. }
  55. policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
  56. if req.CA.PathLength != 0 && req.CA.PathLenZero {
  57. log.Infof("ignore invalid 'pathlenzero' value")
  58. } else {
  59. policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
  60. }
  61. }
  62. if req.CRL != "" {
  63. policy.Default.CRL = req.CRL
  64. }
  65. g := &csr.Generator{Validator: validator}
  66. csrPEM, key, err = g.ProcessRequest(req)
  67. if err != nil {
  68. log.Errorf("failed to process request: %v", err)
  69. key = nil
  70. return
  71. }
  72. priv, err := helpers.ParsePrivateKeyPEM(key)
  73. if err != nil {
  74. log.Errorf("failed to parse private key: %v", err)
  75. return
  76. }
  77. s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
  78. if err != nil {
  79. log.Errorf("failed to create signer: %v", err)
  80. return
  81. }
  82. signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
  83. cert, err = s.Sign(signReq)
  84. return
  85. }
  86. // NewFromPEM creates a new root certificate from the key file passed in.
  87. func NewFromPEM(req *csr.CertificateRequest, keyFile string) (cert, csrPEM []byte, err error) {
  88. privData, err := helpers.ReadBytes(keyFile)
  89. if err != nil {
  90. return nil, nil, err
  91. }
  92. priv, err := helpers.ParsePrivateKeyPEM(privData)
  93. if err != nil {
  94. return nil, nil, err
  95. }
  96. return NewFromSigner(req, priv)
  97. }
  98. // RenewFromPEM re-creates a root certificate from the CA cert and key
  99. // files. The resulting root certificate will have the input CA certificate
  100. // as the template and have the same expiry length. E.g. the existing CA
  101. // is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
  102. // will be valid from now and expire in one year as well.
  103. func RenewFromPEM(caFile, keyFile string) ([]byte, error) {
  104. caBytes, err := helpers.ReadBytes(caFile)
  105. if err != nil {
  106. return nil, err
  107. }
  108. ca, err := helpers.ParseCertificatePEM(caBytes)
  109. if err != nil {
  110. return nil, err
  111. }
  112. keyBytes, err := helpers.ReadBytes(keyFile)
  113. if err != nil {
  114. return nil, err
  115. }
  116. key, err := helpers.ParsePrivateKeyPEM(keyBytes)
  117. if err != nil {
  118. return nil, err
  119. }
  120. return RenewFromSigner(ca, key)
  121. }
  122. // NewFromSigner creates a new root certificate from a crypto.Signer.
  123. func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) {
  124. policy := CAPolicy()
  125. if req.CA != nil {
  126. if req.CA.Expiry != "" {
  127. policy.Default.ExpiryString = req.CA.Expiry
  128. policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
  129. if err != nil {
  130. return nil, nil, err
  131. }
  132. }
  133. policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
  134. if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
  135. log.Infof("ignore invalid 'pathlenzero' value")
  136. } else {
  137. policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
  138. }
  139. }
  140. csrPEM, err = csr.Generate(priv, req)
  141. if err != nil {
  142. return nil, nil, err
  143. }
  144. s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
  145. if err != nil {
  146. log.Errorf("failed to create signer: %v", err)
  147. return
  148. }
  149. signReq := signer.SignRequest{Request: string(csrPEM)}
  150. cert, err = s.Sign(signReq)
  151. return
  152. }
  153. // RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer.
  154. // The resulting root certificate will have ca certificate
  155. // as the template and have the same expiry length. E.g. the existing CA
  156. // is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
  157. // will be valid from now and expire in one year as well.
  158. func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
  159. if !ca.IsCA {
  160. return nil, errors.New("input certificate is not a CA cert")
  161. }
  162. // matching certificate public key vs private key
  163. switch {
  164. case ca.PublicKeyAlgorithm == x509.RSA:
  165. var rsaPublicKey *rsa.PublicKey
  166. var ok bool
  167. if rsaPublicKey, ok = priv.Public().(*rsa.PublicKey); !ok {
  168. return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
  169. }
  170. if ca.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 {
  171. return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
  172. }
  173. case ca.PublicKeyAlgorithm == x509.ECDSA:
  174. var ecdsaPublicKey *ecdsa.PublicKey
  175. var ok bool
  176. if ecdsaPublicKey, ok = priv.Public().(*ecdsa.PublicKey); !ok {
  177. return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
  178. }
  179. if ca.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 {
  180. return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
  181. }
  182. default:
  183. return nil, cferr.New(cferr.PrivateKeyError, cferr.NotRSAOrECC)
  184. }
  185. req := csr.ExtractCertificateRequest(ca)
  186. cert, _, err := NewFromSigner(req, priv)
  187. return cert, err
  188. }
  189. // CAPolicy contains the CA issuing policy as default policy.
  190. var CAPolicy = func() *config.Signing {
  191. return &config.Signing{
  192. Default: &config.SigningProfile{
  193. Usage: []string{"cert sign", "crl sign"},
  194. ExpiryString: "43800h",
  195. Expiry: 5 * helpers.OneYear,
  196. CAConstraint: config.CAConstraint{IsCA: true},
  197. },
  198. }
  199. }
  200. // Update copies the CA certificate, updates the NotBefore and
  201. // NotAfter fields, and then re-signs the certificate.
  202. func Update(ca *x509.Certificate, priv crypto.Signer) (cert []byte, err error) {
  203. copy, err := x509.ParseCertificate(ca.Raw)
  204. if err != nil {
  205. return
  206. }
  207. validity := ca.NotAfter.Sub(ca.NotBefore)
  208. copy.NotBefore = time.Now().Round(time.Minute).Add(-5 * time.Minute)
  209. copy.NotAfter = copy.NotBefore.Add(validity)
  210. cert, err = x509.CreateCertificate(rand.Reader, copy, copy, priv.Public(), priv)
  211. if err != nil {
  212. return
  213. }
  214. cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert})
  215. return
  216. }