csr.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. // Package csr implements certificate requests for CFSSL.
  2. package csr
  3. import (
  4. "crypto"
  5. "crypto/ecdsa"
  6. "crypto/ed25519"
  7. "crypto/elliptic"
  8. "crypto/rand"
  9. "crypto/rsa"
  10. "crypto/x509"
  11. "crypto/x509/pkix"
  12. "encoding/asn1"
  13. "encoding/pem"
  14. "errors"
  15. "fmt"
  16. "io"
  17. "net"
  18. "net/mail"
  19. "net/url"
  20. "strconv"
  21. "strings"
  22. cferr "github.com/cloudflare/cfssl/errors"
  23. "github.com/cloudflare/cfssl/helpers"
  24. "github.com/cloudflare/cfssl/helpers/derhelpers"
  25. "github.com/cloudflare/cfssl/log"
  26. )
  27. const (
  28. curveP256 = 256
  29. curveP384 = 384
  30. curveP521 = 521
  31. )
  32. // A Name contains the SubjectInfo fields.
  33. type Name struct {
  34. C string `json:"C,omitempty" yaml:"C,omitempty"` // Country
  35. ST string `json:"ST,omitempty" yaml:"ST,omitempty"` // State
  36. L string `json:"L,omitempty" yaml:"L,omitempty"` // Locality
  37. O string `json:"O,omitempty" yaml:"O,omitempty"` // OrganisationName
  38. OU string `json:"OU,omitempty" yaml:"OU,omitempty"` // OrganisationalUnitName
  39. E string `json:"E,omitempty" yaml:"E,omitempty"`
  40. SerialNumber string `json:"SerialNumber,omitempty" yaml:"SerialNumber,omitempty"`
  41. OID map[string]string `json:"OID,omitempty", yaml:"OID,omitempty"`
  42. }
  43. // A KeyRequest contains the algorithm and key size for a new private key.
  44. type KeyRequest struct {
  45. A string `json:"algo" yaml:"algo"`
  46. S int `json:"size" yaml:"size"`
  47. }
  48. // NewKeyRequest returns a default KeyRequest.
  49. func NewKeyRequest() *KeyRequest {
  50. return &KeyRequest{"ecdsa", curveP256}
  51. }
  52. // Algo returns the requested key algorithm represented as a string.
  53. func (kr *KeyRequest) Algo() string {
  54. return kr.A
  55. }
  56. // Size returns the requested key size.
  57. func (kr *KeyRequest) Size() int {
  58. return kr.S
  59. }
  60. // Generate generates a key as specified in the request. Currently,
  61. // only ECDSA, RSA and ed25519 algorithms are supported.
  62. func (kr *KeyRequest) Generate() (crypto.PrivateKey, error) {
  63. log.Debugf("generate key from request: algo=%s, size=%d", kr.Algo(), kr.Size())
  64. switch kr.Algo() {
  65. case "rsa":
  66. if kr.Size() < 2048 {
  67. return nil, errors.New("RSA key is too weak")
  68. }
  69. if kr.Size() > 8192 {
  70. return nil, errors.New("RSA key size too large")
  71. }
  72. return rsa.GenerateKey(rand.Reader, kr.Size())
  73. case "ecdsa":
  74. var curve elliptic.Curve
  75. switch kr.Size() {
  76. case curveP256:
  77. curve = elliptic.P256()
  78. case curveP384:
  79. curve = elliptic.P384()
  80. case curveP521:
  81. curve = elliptic.P521()
  82. default:
  83. return nil, errors.New("invalid curve")
  84. }
  85. return ecdsa.GenerateKey(curve, rand.Reader)
  86. case "ed25519":
  87. seed := make([]byte, ed25519.SeedSize)
  88. if _, err := io.ReadFull(rand.Reader, seed); err != nil {
  89. return nil, err
  90. }
  91. return ed25519.NewKeyFromSeed(seed), nil
  92. default:
  93. return nil, errors.New("invalid algorithm")
  94. }
  95. }
  96. // SigAlgo returns an appropriate X.509 signature algorithm given the
  97. // key request's type and size.
  98. func (kr *KeyRequest) SigAlgo() x509.SignatureAlgorithm {
  99. switch kr.Algo() {
  100. case "rsa":
  101. switch {
  102. case kr.Size() >= 4096:
  103. return x509.SHA512WithRSA
  104. case kr.Size() >= 3072:
  105. return x509.SHA384WithRSA
  106. case kr.Size() >= 2048:
  107. return x509.SHA256WithRSA
  108. default:
  109. return x509.SHA1WithRSA
  110. }
  111. case "ecdsa":
  112. switch kr.Size() {
  113. case curveP521:
  114. return x509.ECDSAWithSHA512
  115. case curveP384:
  116. return x509.ECDSAWithSHA384
  117. case curveP256:
  118. return x509.ECDSAWithSHA256
  119. default:
  120. return x509.ECDSAWithSHA1
  121. }
  122. case "ed25519":
  123. return x509.PureEd25519
  124. default:
  125. return x509.UnknownSignatureAlgorithm
  126. }
  127. }
  128. // CAConfig is a section used in the requests initialising a new CA.
  129. type CAConfig struct {
  130. PathLength int `json:"pathlen" yaml:"pathlen"`
  131. PathLenZero bool `json:"pathlenzero" yaml:"pathlenzero"`
  132. Expiry string `json:"expiry" yaml:"expiry"`
  133. Backdate string `json:"backdate" yaml:"backdate"`
  134. }
  135. // A CertificateRequest encapsulates the API interface to the
  136. // certificate request functionality.
  137. type CertificateRequest struct {
  138. CN string `json:"CN" yaml:"CN"`
  139. Names []Name `json:"names" yaml:"names"`
  140. Hosts []string `json:"hosts" yaml:"hosts"`
  141. KeyRequest *KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
  142. CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
  143. SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
  144. DelegationEnabled bool `json:"delegation_enabled,omitempty" yaml:"delegation_enabled,omitempty"`
  145. Extensions []pkix.Extension `json:"extensions,omitempty" yaml:"extensions,omitempty"`
  146. CRL string `json:"crl_url,omitempty" yaml:"crl_url,omitempty"`
  147. }
  148. // New returns a new, empty CertificateRequest with a
  149. // KeyRequest.
  150. func New() *CertificateRequest {
  151. return &CertificateRequest{
  152. KeyRequest: NewKeyRequest(),
  153. }
  154. }
  155. // appendIf appends to a if s is not an empty string.
  156. func appendIf(s string, a *[]string) {
  157. if s != "" {
  158. *a = append(*a, s)
  159. }
  160. }
  161. // OIDFromString creates an ASN1 ObjectIdentifier from its string representation
  162. func OIDFromString(s string) (asn1.ObjectIdentifier, error) {
  163. var oid []int
  164. parts := strings.Split(s, ".")
  165. if len(parts) < 1 {
  166. return oid, fmt.Errorf("invalid OID string: %s", s)
  167. }
  168. for _, p := range parts {
  169. i, err := strconv.Atoi(p)
  170. if err != nil {
  171. return nil, fmt.Errorf("invalid OID part %s", p)
  172. }
  173. oid = append(oid, i)
  174. }
  175. return oid, nil
  176. }
  177. // Name returns the PKIX name for the request.
  178. func (cr *CertificateRequest) Name() (pkix.Name, error) {
  179. var name pkix.Name
  180. name.CommonName = cr.CN
  181. for _, n := range cr.Names {
  182. appendIf(n.C, &name.Country)
  183. appendIf(n.ST, &name.Province)
  184. appendIf(n.L, &name.Locality)
  185. appendIf(n.O, &name.Organization)
  186. appendIf(n.OU, &name.OrganizationalUnit)
  187. for k, v := range n.OID {
  188. oid, err := OIDFromString(k)
  189. if err != nil {
  190. return name, err
  191. }
  192. name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: oid, Value: v})
  193. }
  194. if n.E != "" {
  195. name.ExtraNames = append(name.ExtraNames, pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: n.E})
  196. }
  197. }
  198. name.SerialNumber = cr.SerialNumber
  199. return name, nil
  200. }
  201. // BasicConstraints CSR information RFC 5280, 4.2.1.9
  202. type BasicConstraints struct {
  203. IsCA bool `asn1:"optional"`
  204. MaxPathLen int `asn1:"optional,default:-1"`
  205. }
  206. // ParseRequest takes a certificate request and generates a key and
  207. // CSR from it. It does no validation -- caveat emptor. It will,
  208. // however, fail if the key request is not valid (i.e., an unsupported
  209. // curve or RSA key size). The lack of validation was specifically
  210. // chosen to allow the end user to define a policy and validate the
  211. // request appropriately before calling this function.
  212. func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
  213. log.Info("received CSR")
  214. if req.KeyRequest == nil {
  215. req.KeyRequest = NewKeyRequest()
  216. }
  217. log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size())
  218. priv, err := req.KeyRequest.Generate()
  219. if err != nil {
  220. err = cferr.Wrap(cferr.PrivateKeyError, cferr.GenerationFailed, err)
  221. return
  222. }
  223. switch priv := priv.(type) {
  224. case *rsa.PrivateKey:
  225. key = x509.MarshalPKCS1PrivateKey(priv)
  226. block := pem.Block{
  227. Type: "RSA PRIVATE KEY",
  228. Bytes: key,
  229. }
  230. key = pem.EncodeToMemory(&block)
  231. case *ecdsa.PrivateKey:
  232. key, err = x509.MarshalECPrivateKey(priv)
  233. if err != nil {
  234. err = cferr.Wrap(cferr.PrivateKeyError, cferr.Unknown, err)
  235. return
  236. }
  237. block := pem.Block{
  238. Type: "EC PRIVATE KEY",
  239. Bytes: key,
  240. }
  241. key = pem.EncodeToMemory(&block)
  242. case ed25519.PrivateKey:
  243. key, err = derhelpers.MarshalEd25519PrivateKey(priv)
  244. if err != nil {
  245. err = cferr.Wrap(cferr.PrivateKeyError, cferr.Unknown, err)
  246. return
  247. }
  248. block := pem.Block{
  249. Type: "Ed25519 PRIVATE KEY",
  250. Bytes: key,
  251. }
  252. key = pem.EncodeToMemory(&block)
  253. default:
  254. panic("Generate should have failed to produce a valid key.")
  255. }
  256. csr, err = Generate(priv.(crypto.Signer), req)
  257. if err != nil {
  258. log.Errorf("failed to generate a CSR: %v", err)
  259. err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
  260. }
  261. return
  262. }
  263. // ExtractCertificateRequest extracts a CertificateRequest from
  264. // x509.Certificate. It is aimed to used for generating a new certificate
  265. // from an existing certificate. For a root certificate, the CA expiry
  266. // length is calculated as the duration between cert.NotAfter and cert.NotBefore.
  267. func ExtractCertificateRequest(cert *x509.Certificate) *CertificateRequest {
  268. req := New()
  269. req.CN = cert.Subject.CommonName
  270. req.Names = getNames(cert.Subject)
  271. req.Hosts = getHosts(cert)
  272. req.SerialNumber = cert.Subject.SerialNumber
  273. if cert.IsCA {
  274. req.CA = new(CAConfig)
  275. // CA expiry length is calculated based on the input cert
  276. // issue date and expiry date.
  277. req.CA.Expiry = cert.NotAfter.Sub(cert.NotBefore).String()
  278. req.CA.PathLength = cert.MaxPathLen
  279. req.CA.PathLenZero = cert.MaxPathLenZero
  280. }
  281. return req
  282. }
  283. func getHosts(cert *x509.Certificate) []string {
  284. var hosts []string
  285. for _, ip := range cert.IPAddresses {
  286. hosts = append(hosts, ip.String())
  287. }
  288. hosts = append(hosts, cert.DNSNames...)
  289. hosts = append(hosts, cert.EmailAddresses...)
  290. for _, uri := range cert.URIs {
  291. hosts = append(hosts, uri.String())
  292. }
  293. return hosts
  294. }
  295. // getNames returns an array of Names from the certificate
  296. // It only cares about Country, Organization, OrganizationalUnit, Locality, Province
  297. func getNames(sub pkix.Name) []Name {
  298. // anonymous func for finding the max of a list of integer
  299. max := func(v1 int, vn ...int) (max int) {
  300. max = v1
  301. for i := 0; i < len(vn); i++ {
  302. if vn[i] > max {
  303. max = vn[i]
  304. }
  305. }
  306. return max
  307. }
  308. nc := len(sub.Country)
  309. norg := len(sub.Organization)
  310. nou := len(sub.OrganizationalUnit)
  311. nl := len(sub.Locality)
  312. np := len(sub.Province)
  313. n := max(nc, norg, nou, nl, np)
  314. names := make([]Name, n)
  315. for i := range names {
  316. if i < nc {
  317. names[i].C = sub.Country[i]
  318. }
  319. if i < norg {
  320. names[i].O = sub.Organization[i]
  321. }
  322. if i < nou {
  323. names[i].OU = sub.OrganizationalUnit[i]
  324. }
  325. if i < nl {
  326. names[i].L = sub.Locality[i]
  327. }
  328. if i < np {
  329. names[i].ST = sub.Province[i]
  330. }
  331. }
  332. return names
  333. }
  334. // A Generator is responsible for validating certificate requests.
  335. type Generator struct {
  336. Validator func(*CertificateRequest) error
  337. }
  338. // ProcessRequest validates and processes the incoming request. It is
  339. // a wrapper around a validator and the ParseRequest function.
  340. func (g *Generator) ProcessRequest(req *CertificateRequest) (csr, key []byte, err error) {
  341. log.Info("generate received request")
  342. err = g.Validator(req)
  343. if err != nil {
  344. log.Warningf("invalid request: %v", err)
  345. return nil, nil, err
  346. }
  347. csr, key, err = ParseRequest(req)
  348. if err != nil {
  349. return nil, nil, err
  350. }
  351. return
  352. }
  353. // IsNameEmpty returns true if the name has no identifying information in it.
  354. func IsNameEmpty(n Name) bool {
  355. empty := func(s string) bool { return strings.TrimSpace(s) == "" }
  356. if empty(n.C) && empty(n.ST) && empty(n.L) && empty(n.O) && empty(n.OU) {
  357. return true
  358. }
  359. return false
  360. }
  361. // Regenerate uses the provided CSR as a template for signing a new
  362. // CSR using priv.
  363. func Regenerate(priv crypto.Signer, csr []byte) ([]byte, error) {
  364. req, extra, err := helpers.ParseCSR(csr)
  365. if err != nil {
  366. return nil, err
  367. } else if len(extra) > 0 {
  368. return nil, errors.New("csr: trailing data in certificate request")
  369. }
  370. return x509.CreateCertificateRequest(rand.Reader, req, priv)
  371. }
  372. // GenerateDER creates a new CSR(ASN1 DER encoded) from a CertificateRequest structure and
  373. // an existing key. The KeyRequest field is ignored.
  374. func GenerateDER(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
  375. sigAlgo := helpers.SignerAlgo(priv)
  376. if sigAlgo == x509.UnknownSignatureAlgorithm {
  377. return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
  378. }
  379. subj, err := req.Name()
  380. if err != nil {
  381. return nil, err
  382. }
  383. var tpl = x509.CertificateRequest{
  384. Subject: subj,
  385. SignatureAlgorithm: sigAlgo,
  386. }
  387. for i := range req.Hosts {
  388. if ip := net.ParseIP(req.Hosts[i]); ip != nil {
  389. tpl.IPAddresses = append(tpl.IPAddresses, ip)
  390. } else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil {
  391. tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address)
  392. } else if uri, err := url.ParseRequestURI(req.Hosts[i]); err == nil && uri != nil {
  393. tpl.URIs = append(tpl.URIs, uri)
  394. } else {
  395. tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
  396. }
  397. }
  398. tpl.ExtraExtensions = []pkix.Extension{}
  399. if req.CA != nil {
  400. err = appendCAInfoToCSR(req.CA, &tpl)
  401. if err != nil {
  402. err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err)
  403. return
  404. }
  405. }
  406. if req.DelegationEnabled {
  407. tpl.ExtraExtensions = append(tpl.Extensions, helpers.DelegationExtension)
  408. }
  409. if req.Extensions != nil {
  410. err = appendExtensionsToCSR(req.Extensions, &tpl)
  411. if err != nil {
  412. err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err)
  413. return
  414. }
  415. }
  416. csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
  417. if err != nil {
  418. log.Errorf("failed to generate a CSR: %v", err)
  419. err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
  420. return
  421. }
  422. return
  423. }
  424. // Generate creates a new CSR(PEM encoded) from a CertificateRequest structure and
  425. // an existing key. The KeyRequest field is ignored.
  426. func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
  427. csr, err = GenerateDER(priv, req)
  428. if err != nil {
  429. return
  430. }
  431. block := pem.Block{
  432. Type: "CERTIFICATE REQUEST",
  433. Bytes: csr,
  434. }
  435. log.Info("encoded CSR")
  436. csr = pem.EncodeToMemory(&block)
  437. return
  438. }
  439. // appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR
  440. func appendCAInfoToCSR(reqConf *CAConfig, csr *x509.CertificateRequest) error {
  441. pathlen := reqConf.PathLength
  442. if pathlen == 0 && !reqConf.PathLenZero {
  443. pathlen = -1
  444. }
  445. val, err := asn1.Marshal(BasicConstraints{true, pathlen})
  446. if err != nil {
  447. return err
  448. }
  449. csr.ExtraExtensions = append(csr.ExtraExtensions, pkix.Extension{
  450. Id: asn1.ObjectIdentifier{2, 5, 29, 19},
  451. Value: val,
  452. Critical: true,
  453. })
  454. return nil
  455. }
  456. // appendCAInfoToCSR appends user-defined extension to a CSR
  457. func appendExtensionsToCSR(extensions []pkix.Extension, csr *x509.CertificateRequest) error {
  458. csr.ExtraExtensions = append(csr.ExtraExtensions, extensions...)
  459. return nil
  460. }