csr.go 11 KB

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