initca.go 7.4 KB

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