helpers.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. // Package helpers implements utility functionality common to many
  2. // CFSSL packages.
  3. package helpers
  4. import (
  5. "bytes"
  6. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/rsa"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "encoding/asn1"
  13. "encoding/pem"
  14. "errors"
  15. "io/ioutil"
  16. "math/big"
  17. "strings"
  18. "time"
  19. "github.com/cloudflare/cfssl/crypto/pkcs7"
  20. cferr "github.com/cloudflare/cfssl/errors"
  21. "github.com/cloudflare/cfssl/helpers/derhelpers"
  22. "github.com/cloudflare/cfssl/log"
  23. "golang.org/x/crypto/pkcs12"
  24. )
  25. // OneYear is a time.Duration representing a year's worth of seconds.
  26. const OneYear = 8760 * time.Hour
  27. // OneDay is a time.Duration representing a day's worth of seconds.
  28. const OneDay = 24 * time.Hour
  29. // InclusiveDate returns the time.Time representation of a date - 1
  30. // nanosecond. This allows time.After to be used inclusively.
  31. func InclusiveDate(year int, month time.Month, day int) time.Time {
  32. return time.Date(year, month, day, 0, 0, 0, 0, time.UTC).Add(-1 * time.Nanosecond)
  33. }
  34. // Jul2012 is the July 2012 CAB Forum deadline for when CAs must stop
  35. // issuing certificates valid for more than 5 years.
  36. var Jul2012 = InclusiveDate(2012, time.July, 01)
  37. // Apr2015 is the April 2015 CAB Forum deadline for when CAs must stop
  38. // issuing certificates valid for more than 39 months.
  39. var Apr2015 = InclusiveDate(2015, time.April, 01)
  40. // KeyLength returns the bit size of ECDSA or RSA PublicKey
  41. func KeyLength(key interface{}) int {
  42. if key == nil {
  43. return 0
  44. }
  45. if ecdsaKey, ok := key.(*ecdsa.PublicKey); ok {
  46. return ecdsaKey.Curve.Params().BitSize
  47. } else if rsaKey, ok := key.(*rsa.PublicKey); ok {
  48. return rsaKey.N.BitLen()
  49. }
  50. return 0
  51. }
  52. // ExpiryTime returns the time when the certificate chain is expired.
  53. func ExpiryTime(chain []*x509.Certificate) (notAfter time.Time) {
  54. if len(chain) == 0 {
  55. return
  56. }
  57. notAfter = chain[0].NotAfter
  58. for _, cert := range chain {
  59. if notAfter.After(cert.NotAfter) {
  60. notAfter = cert.NotAfter
  61. }
  62. }
  63. return
  64. }
  65. // MonthsValid returns the number of months for which a certificate is valid.
  66. func MonthsValid(c *x509.Certificate) int {
  67. issued := c.NotBefore
  68. expiry := c.NotAfter
  69. years := (expiry.Year() - issued.Year())
  70. months := years*12 + int(expiry.Month()) - int(issued.Month())
  71. // Round up if valid for less than a full month
  72. if expiry.Day() > issued.Day() {
  73. months++
  74. }
  75. return months
  76. }
  77. // ValidExpiry determines if a certificate is valid for an acceptable
  78. // length of time per the CA/Browser Forum baseline requirements.
  79. // See https://cabforum.org/wp-content/uploads/CAB-Forum-BR-1.3.0.pdf
  80. func ValidExpiry(c *x509.Certificate) bool {
  81. issued := c.NotBefore
  82. var maxMonths int
  83. switch {
  84. case issued.After(Apr2015):
  85. maxMonths = 39
  86. case issued.After(Jul2012):
  87. maxMonths = 60
  88. case issued.Before(Jul2012):
  89. maxMonths = 120
  90. }
  91. if MonthsValid(c) > maxMonths {
  92. return false
  93. }
  94. return true
  95. }
  96. // SignatureString returns the TLS signature string corresponding to
  97. // an X509 signature algorithm.
  98. func SignatureString(alg x509.SignatureAlgorithm) string {
  99. switch alg {
  100. case x509.MD2WithRSA:
  101. return "MD2WithRSA"
  102. case x509.MD5WithRSA:
  103. return "MD5WithRSA"
  104. case x509.SHA1WithRSA:
  105. return "SHA1WithRSA"
  106. case x509.SHA256WithRSA:
  107. return "SHA256WithRSA"
  108. case x509.SHA384WithRSA:
  109. return "SHA384WithRSA"
  110. case x509.SHA512WithRSA:
  111. return "SHA512WithRSA"
  112. case x509.DSAWithSHA1:
  113. return "DSAWithSHA1"
  114. case x509.DSAWithSHA256:
  115. return "DSAWithSHA256"
  116. case x509.ECDSAWithSHA1:
  117. return "ECDSAWithSHA1"
  118. case x509.ECDSAWithSHA256:
  119. return "ECDSAWithSHA256"
  120. case x509.ECDSAWithSHA384:
  121. return "ECDSAWithSHA384"
  122. case x509.ECDSAWithSHA512:
  123. return "ECDSAWithSHA512"
  124. default:
  125. return "Unknown Signature"
  126. }
  127. }
  128. // HashAlgoString returns the hash algorithm name contains in the signature
  129. // method.
  130. func HashAlgoString(alg x509.SignatureAlgorithm) string {
  131. switch alg {
  132. case x509.MD2WithRSA:
  133. return "MD2"
  134. case x509.MD5WithRSA:
  135. return "MD5"
  136. case x509.SHA1WithRSA:
  137. return "SHA1"
  138. case x509.SHA256WithRSA:
  139. return "SHA256"
  140. case x509.SHA384WithRSA:
  141. return "SHA384"
  142. case x509.SHA512WithRSA:
  143. return "SHA512"
  144. case x509.DSAWithSHA1:
  145. return "SHA1"
  146. case x509.DSAWithSHA256:
  147. return "SHA256"
  148. case x509.ECDSAWithSHA1:
  149. return "SHA1"
  150. case x509.ECDSAWithSHA256:
  151. return "SHA256"
  152. case x509.ECDSAWithSHA384:
  153. return "SHA384"
  154. case x509.ECDSAWithSHA512:
  155. return "SHA512"
  156. default:
  157. return "Unknown Hash Algorithm"
  158. }
  159. }
  160. // EncodeCertificatesPEM encodes a number of x509 certficates to PEM
  161. func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
  162. var buffer bytes.Buffer
  163. for _, cert := range certs {
  164. pem.Encode(&buffer, &pem.Block{
  165. Type: "CERTIFICATE",
  166. Bytes: cert.Raw,
  167. })
  168. }
  169. return buffer.Bytes()
  170. }
  171. // EncodeCertificatePEM encodes a single x509 certficates to PEM
  172. func EncodeCertificatePEM(cert *x509.Certificate) []byte {
  173. return EncodeCertificatesPEM([]*x509.Certificate{cert})
  174. }
  175. // ParseCertificatesPEM parses a sequence of PEM-encoded certificate and returns them,
  176. // can handle PEM encoded PKCS #7 structures.
  177. func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) {
  178. var certs []*x509.Certificate
  179. var err error
  180. certsPEM = bytes.TrimSpace(certsPEM)
  181. for len(certsPEM) > 0 {
  182. var cert []*x509.Certificate
  183. cert, certsPEM, err = ParseOneCertificateFromPEM(certsPEM)
  184. if err != nil {
  185. return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
  186. } else if cert == nil {
  187. break
  188. }
  189. certs = append(certs, cert...)
  190. }
  191. if len(certsPEM) > 0 {
  192. return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  193. }
  194. return certs, nil
  195. }
  196. // ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key,
  197. // either PKCS #7, PKCS #12, or raw x509.
  198. func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certificate, key crypto.Signer, err error) {
  199. certsDER = bytes.TrimSpace(certsDER)
  200. pkcs7data, err := pkcs7.ParsePKCS7(certsDER)
  201. if err != nil {
  202. var pkcs12data interface{}
  203. certs = make([]*x509.Certificate, 1)
  204. pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password)
  205. if err != nil {
  206. certs, err = x509.ParseCertificates(certsDER)
  207. if err != nil {
  208. return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  209. }
  210. } else {
  211. key = pkcs12data.(crypto.Signer)
  212. }
  213. } else {
  214. if pkcs7data.ContentInfo != "SignedData" {
  215. return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info"))
  216. }
  217. certs = pkcs7data.Content.SignedData.Certificates
  218. }
  219. if certs == nil {
  220. return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  221. }
  222. return certs, key, nil
  223. }
  224. // ParseSelfSignedCertificatePEM parses a PEM-encoded certificate and check if it is self-signed.
  225. func ParseSelfSignedCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
  226. cert, err := ParseCertificatePEM(certPEM)
  227. if err != nil {
  228. return nil, err
  229. }
  230. if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
  231. return nil, cferr.Wrap(cferr.CertificateError, cferr.VerifyFailed, err)
  232. }
  233. return cert, nil
  234. }
  235. // ParseCertificatePEM parses and returns a PEM-encoded certificate,
  236. // can handle PEM encoded PKCS #7 structures.
  237. func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
  238. certPEM = bytes.TrimSpace(certPEM)
  239. cert, rest, err := ParseOneCertificateFromPEM(certPEM)
  240. if err != nil {
  241. // Log the actual parsing error but throw a default parse error message.
  242. log.Debugf("Certificate parsing error: %v", err)
  243. return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
  244. } else if cert == nil {
  245. return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
  246. } else if len(rest) > 0 {
  247. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PEM file should contain only one object"))
  248. } else if len(cert) > 1 {
  249. return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PKCS7 object in the PEM file should contain only one certificate"))
  250. }
  251. return cert[0], nil
  252. }
  253. // ParseOneCertificateFromPEM attempts to parse one PEM encoded certificate object,
  254. // either a raw x509 certificate or a PKCS #7 structure possibly containing
  255. // multiple certificates, from the top of certsPEM, which itself may
  256. // contain multiple PEM encoded certificate objects.
  257. func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, error) {
  258. block, rest := pem.Decode(certsPEM)
  259. if block == nil {
  260. return nil, rest, nil
  261. }
  262. cert, err := x509.ParseCertificate(block.Bytes)
  263. if err != nil {
  264. pkcs7data, err := pkcs7.ParsePKCS7(block.Bytes)
  265. if err != nil {
  266. return nil, rest, err
  267. }
  268. if pkcs7data.ContentInfo != "SignedData" {
  269. return nil, rest, errors.New("only PKCS #7 Signed Data Content Info supported for certificate parsing")
  270. }
  271. certs := pkcs7data.Content.SignedData.Certificates
  272. if certs == nil {
  273. return nil, rest, errors.New("PKCS #7 structure contains no certificates")
  274. }
  275. return certs, rest, nil
  276. }
  277. var certs = []*x509.Certificate{cert}
  278. return certs, rest, nil
  279. }
  280. // LoadPEMCertPool loads a pool of PEM certificates from file.
  281. func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
  282. if certsFile == "" {
  283. return nil, nil
  284. }
  285. pemCerts, err := ioutil.ReadFile(certsFile)
  286. if err != nil {
  287. return nil, err
  288. }
  289. return PEMToCertPool(pemCerts)
  290. }
  291. // PEMToCertPool concerts PEM certificates to a CertPool.
  292. func PEMToCertPool(pemCerts []byte) (*x509.CertPool, error) {
  293. if len(pemCerts) == 0 {
  294. return nil, nil
  295. }
  296. certPool := x509.NewCertPool()
  297. if !certPool.AppendCertsFromPEM(pemCerts) {
  298. return nil, errors.New("failed to load cert pool")
  299. }
  300. return certPool, nil
  301. }
  302. // ParsePrivateKeyPEM parses and returns a PEM-encoded private
  303. // key. The private key may be either an unencrypted PKCS#8, PKCS#1,
  304. // or elliptic private key.
  305. func ParsePrivateKeyPEM(keyPEM []byte) (key crypto.Signer, err error) {
  306. return ParsePrivateKeyPEMWithPassword(keyPEM, nil)
  307. }
  308. // ParsePrivateKeyPEMWithPassword parses and returns a PEM-encoded private
  309. // key. The private key may be a potentially encrypted PKCS#8, PKCS#1,
  310. // or elliptic private key.
  311. func ParsePrivateKeyPEMWithPassword(keyPEM []byte, password []byte) (key crypto.Signer, err error) {
  312. keyDER, err := GetKeyDERFromPEM(keyPEM, password)
  313. if err != nil {
  314. return nil, err
  315. }
  316. return derhelpers.ParsePrivateKeyDER(keyDER)
  317. }
  318. // GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes.
  319. func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
  320. keyDER, _ := pem.Decode(in)
  321. if keyDER != nil {
  322. if procType, ok := keyDER.Headers["Proc-Type"]; ok {
  323. if strings.Contains(procType, "ENCRYPTED") {
  324. if password != nil {
  325. return x509.DecryptPEMBlock(keyDER, password)
  326. }
  327. return nil, cferr.New(cferr.PrivateKeyError, cferr.Encrypted)
  328. }
  329. }
  330. return keyDER.Bytes, nil
  331. }
  332. return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed)
  333. }
  334. // CheckSignature verifies a signature made by the key on a CSR, such
  335. // as on the CSR itself.
  336. func CheckSignature(csr *x509.CertificateRequest, algo x509.SignatureAlgorithm, signed, signature []byte) error {
  337. var hashType crypto.Hash
  338. switch algo {
  339. case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
  340. hashType = crypto.SHA1
  341. case x509.SHA256WithRSA, x509.ECDSAWithSHA256:
  342. hashType = crypto.SHA256
  343. case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
  344. hashType = crypto.SHA384
  345. case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
  346. hashType = crypto.SHA512
  347. default:
  348. return x509.ErrUnsupportedAlgorithm
  349. }
  350. if !hashType.Available() {
  351. return x509.ErrUnsupportedAlgorithm
  352. }
  353. h := hashType.New()
  354. h.Write(signed)
  355. digest := h.Sum(nil)
  356. switch pub := csr.PublicKey.(type) {
  357. case *rsa.PublicKey:
  358. return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
  359. case *ecdsa.PublicKey:
  360. ecdsaSig := new(struct{ R, S *big.Int })
  361. if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
  362. return err
  363. }
  364. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  365. return errors.New("x509: ECDSA signature contained zero or negative values")
  366. }
  367. if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
  368. return errors.New("x509: ECDSA verification failure")
  369. }
  370. return nil
  371. }
  372. return x509.ErrUnsupportedAlgorithm
  373. }
  374. // ParseCSR parses a PEM- or DER-encoded PKCS #10 certificate signing request.
  375. func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error) {
  376. in = bytes.TrimSpace(in)
  377. p, rest := pem.Decode(in)
  378. if p != nil {
  379. if p.Type != "NEW CERTIFICATE REQUEST" && p.Type != "CERTIFICATE REQUEST" {
  380. return nil, rest, cferr.New(cferr.CSRError, cferr.BadRequest)
  381. }
  382. csr, err = x509.ParseCertificateRequest(p.Bytes)
  383. } else {
  384. csr, err = x509.ParseCertificateRequest(in)
  385. }
  386. if err != nil {
  387. return nil, rest, err
  388. }
  389. err = CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
  390. if err != nil {
  391. return nil, rest, err
  392. }
  393. return csr, rest, nil
  394. }
  395. // ParseCSRPEM parses a PEM-encoded certificiate signing request.
  396. // It does not check the signature. This is useful for dumping data from a CSR
  397. // locally.
  398. func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
  399. block, _ := pem.Decode([]byte(csrPEM))
  400. der := block.Bytes
  401. csrObject, err := x509.ParseCertificateRequest(der)
  402. if err != nil {
  403. return nil, err
  404. }
  405. return csrObject, nil
  406. }
  407. // SignerAlgo returns an X.509 signature algorithm from a crypto.Signer.
  408. func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
  409. switch pub := priv.Public().(type) {
  410. case *rsa.PublicKey:
  411. bitLength := pub.N.BitLen()
  412. switch {
  413. case bitLength >= 4096:
  414. return x509.SHA512WithRSA
  415. case bitLength >= 3072:
  416. return x509.SHA384WithRSA
  417. case bitLength >= 2048:
  418. return x509.SHA256WithRSA
  419. default:
  420. return x509.SHA1WithRSA
  421. }
  422. case *ecdsa.PublicKey:
  423. switch pub.Curve {
  424. case elliptic.P521():
  425. return x509.ECDSAWithSHA512
  426. case elliptic.P384():
  427. return x509.ECDSAWithSHA384
  428. case elliptic.P256():
  429. return x509.ECDSAWithSHA256
  430. default:
  431. return x509.ECDSAWithSHA1
  432. }
  433. default:
  434. return x509.UnknownSignatureAlgorithm
  435. }
  436. }
  437. // LoadClientCertificate load key/certificate from pem files
  438. func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) {
  439. if certFile != "" && keyFile != "" {
  440. cert, err := tls.LoadX509KeyPair(certFile, keyFile)
  441. if err != nil {
  442. log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
  443. return nil, err
  444. }
  445. log.Debug("Client certificate loaded ")
  446. return &cert, nil
  447. }
  448. return nil, nil
  449. }
  450. // CreateTLSConfig creates a tls.Config object from certs and roots
  451. func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config {
  452. var certs []tls.Certificate
  453. if cert != nil {
  454. certs = []tls.Certificate{*cert}
  455. }
  456. return &tls.Config{
  457. Certificates: certs,
  458. RootCAs: remoteCAs,
  459. }
  460. }