signer.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // Package signer implements certificate signature functionality for CFSSL.
  2. package signer
  3. import (
  4. "crypto"
  5. "crypto/ecdsa"
  6. "crypto/ed25519"
  7. "crypto/elliptic"
  8. "crypto/rsa"
  9. "crypto/sha1"
  10. "crypto/x509"
  11. "crypto/x509/pkix"
  12. "encoding/asn1"
  13. "errors"
  14. "math/big"
  15. "net/http"
  16. "strings"
  17. "time"
  18. "github.com/cloudflare/cfssl/certdb"
  19. "github.com/cloudflare/cfssl/config"
  20. "github.com/cloudflare/cfssl/csr"
  21. cferr "github.com/cloudflare/cfssl/errors"
  22. "github.com/cloudflare/cfssl/helpers"
  23. "github.com/cloudflare/cfssl/info"
  24. )
  25. // Subject contains the information that should be used to override the
  26. // subject information when signing a certificate.
  27. type Subject struct {
  28. CN string
  29. Names []csr.Name `json:"names"`
  30. SerialNumber string
  31. }
  32. // Extension represents a raw extension to be included in the certificate. The
  33. // "value" field must be hex encoded.
  34. type Extension struct {
  35. ID config.OID `json:"id"`
  36. Critical bool `json:"critical"`
  37. Value string `json:"value"`
  38. }
  39. // SignRequest stores a signature request, which contains the hostname,
  40. // the CSR, optional subject information, and the signature profile.
  41. //
  42. // Extensions provided in the signRequest are copied into the certificate, as
  43. // long as they are in the ExtensionWhitelist for the signer's policy.
  44. // Extensions requested in the CSR are ignored, except for those processed by
  45. // ParseCertificateRequest (mainly subjectAltName) and DelegationUsage.
  46. type SignRequest struct {
  47. Hosts []string `json:"hosts"`
  48. Request string `json:"certificate_request"`
  49. Subject *Subject `json:"subject,omitempty"`
  50. Profile string `json:"profile"`
  51. CRLOverride string `json:"crl_override"`
  52. Label string `json:"label"`
  53. Serial *big.Int `json:"serial,omitempty"`
  54. Extensions []Extension `json:"extensions,omitempty"`
  55. // If provided, NotBefore will be used without modification (except
  56. // for canonicalization) as the value of the notBefore field of the
  57. // certificate. In particular no backdating adjustment will be made
  58. // when NotBefore is provided.
  59. NotBefore time.Time
  60. // If provided, NotAfter will be used without modification (except
  61. // for canonicalization) as the value of the notAfter field of the
  62. // certificate.
  63. NotAfter time.Time
  64. // If ReturnPrecert is true a certificate with the CT poison extension
  65. // will be returned from the Signer instead of attempting to retrieve
  66. // SCTs and populate the tbsCert with them itself. This precert can then
  67. // be passed to SignFromPrecert with the SCTs in order to create a
  68. // valid certificate.
  69. ReturnPrecert bool
  70. // Arbitrary metadata to be stored in certdb.
  71. Metadata map[string]interface{} `json:"metadata"`
  72. }
  73. // appendIf appends to a if s is not an empty string.
  74. func appendIf(s string, a *[]string) {
  75. if s != "" {
  76. *a = append(*a, s)
  77. }
  78. }
  79. // Name returns the PKIX name for the subject.
  80. func (s *Subject) Name() pkix.Name {
  81. var name pkix.Name
  82. name.CommonName = s.CN
  83. for _, n := range s.Names {
  84. appendIf(n.C, &name.Country)
  85. appendIf(n.ST, &name.Province)
  86. appendIf(n.L, &name.Locality)
  87. appendIf(n.O, &name.Organization)
  88. appendIf(n.OU, &name.OrganizationalUnit)
  89. }
  90. name.SerialNumber = s.SerialNumber
  91. return name
  92. }
  93. // SplitHosts takes a comma-spearated list of hosts and returns a slice
  94. // with the hosts split
  95. func SplitHosts(hostList string) []string {
  96. if hostList == "" {
  97. return nil
  98. }
  99. return strings.Split(hostList, ",")
  100. }
  101. // A Signer contains a CA's certificate and private key for signing
  102. // certificates, a Signing policy to refer to and a SignatureAlgorithm.
  103. type Signer interface {
  104. Info(info.Req) (*info.Resp, error)
  105. Policy() *config.Signing
  106. SetDBAccessor(certdb.Accessor)
  107. GetDBAccessor() certdb.Accessor
  108. SetPolicy(*config.Signing)
  109. SigAlgo() x509.SignatureAlgorithm
  110. Sign(req SignRequest) (cert []byte, err error)
  111. SetReqModifier(func(*http.Request, []byte))
  112. }
  113. // Profile gets the specific profile from the signer
  114. func Profile(s Signer, profile string) (*config.SigningProfile, error) {
  115. var p *config.SigningProfile
  116. policy := s.Policy()
  117. if policy != nil && policy.Profiles != nil && profile != "" {
  118. p = policy.Profiles[profile]
  119. }
  120. if p == nil && policy != nil {
  121. p = policy.Default
  122. }
  123. if p == nil {
  124. return nil, cferr.Wrap(cferr.APIClientError, cferr.ClientHTTPError, errors.New("profile must not be nil"))
  125. }
  126. return p, nil
  127. }
  128. // DefaultSigAlgo returns an appropriate X.509 signature algorithm given
  129. // the CA's private key.
  130. func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
  131. pub := priv.Public()
  132. switch pub := pub.(type) {
  133. case *rsa.PublicKey:
  134. keySize := pub.N.BitLen()
  135. switch {
  136. case keySize >= 4096:
  137. return x509.SHA512WithRSA
  138. case keySize >= 3072:
  139. return x509.SHA384WithRSA
  140. case keySize >= 2048:
  141. return x509.SHA256WithRSA
  142. default:
  143. return x509.SHA1WithRSA
  144. }
  145. case *ecdsa.PublicKey:
  146. switch pub.Curve {
  147. case elliptic.P256():
  148. return x509.ECDSAWithSHA256
  149. case elliptic.P384():
  150. return x509.ECDSAWithSHA384
  151. case elliptic.P521():
  152. return x509.ECDSAWithSHA512
  153. default:
  154. return x509.ECDSAWithSHA1
  155. }
  156. case ed25519.PublicKey:
  157. return x509.PureEd25519
  158. default:
  159. return x509.UnknownSignatureAlgorithm
  160. }
  161. }
  162. func isCommonAttr(t []int) bool {
  163. return (len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 && (t[3] == 3 || (t[3] >= 5 && t[3] <= 11) || t[3] == 17))
  164. }
  165. // ParseCertificateRequest takes an incoming certificate request and
  166. // builds a certificate template from it.
  167. func ParseCertificateRequest(s Signer, p *config.SigningProfile, csrBytes []byte) (template *x509.Certificate, err error) {
  168. csrv, err := x509.ParseCertificateRequest(csrBytes)
  169. if err != nil {
  170. err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
  171. return
  172. }
  173. var r pkix.RDNSequence
  174. _, err = asn1.Unmarshal(csrv.RawSubject, &r)
  175. if err != nil {
  176. err = cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
  177. return
  178. }
  179. var subject pkix.Name
  180. subject.FillFromRDNSequence(&r)
  181. for _, v := range r {
  182. for _, vv := range v {
  183. if !isCommonAttr(vv.Type) {
  184. subject.ExtraNames = append(subject.ExtraNames, vv)
  185. }
  186. }
  187. }
  188. err = csrv.CheckSignature()
  189. if err != nil {
  190. err = cferr.Wrap(cferr.CSRError, cferr.KeyMismatch, err)
  191. return
  192. }
  193. template = &x509.Certificate{
  194. Subject: subject,
  195. PublicKeyAlgorithm: csrv.PublicKeyAlgorithm,
  196. PublicKey: csrv.PublicKey,
  197. SignatureAlgorithm: s.SigAlgo(),
  198. DNSNames: csrv.DNSNames,
  199. IPAddresses: csrv.IPAddresses,
  200. EmailAddresses: csrv.EmailAddresses,
  201. URIs: csrv.URIs,
  202. Extensions: csrv.Extensions,
  203. ExtraExtensions: []pkix.Extension{},
  204. }
  205. for _, val := range csrv.Extensions {
  206. // Check the CSR for the X.509 BasicConstraints (RFC 5280, 4.2.1.9)
  207. // extension and append to template if necessary
  208. if val.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) {
  209. var constraints csr.BasicConstraints
  210. var rest []byte
  211. if rest, err = asn1.Unmarshal(val.Value, &constraints); err != nil {
  212. return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, err)
  213. } else if len(rest) != 0 {
  214. return nil, cferr.Wrap(cferr.CSRError, cferr.ParseFailed, errors.New("x509: trailing data after X.509 BasicConstraints"))
  215. }
  216. template.BasicConstraintsValid = true
  217. template.IsCA = constraints.IsCA
  218. template.MaxPathLen = constraints.MaxPathLen
  219. template.MaxPathLenZero = template.MaxPathLen == 0
  220. } else if val.Id.Equal(helpers.DelegationUsage) {
  221. template.ExtraExtensions = append(template.ExtraExtensions, val)
  222. } else {
  223. // If the profile has 'copy_extensions' to true then lets add it
  224. if p.CopyExtensions {
  225. template.ExtraExtensions = append(template.ExtraExtensions, val)
  226. }
  227. }
  228. }
  229. return
  230. }
  231. type subjectPublicKeyInfo struct {
  232. Algorithm pkix.AlgorithmIdentifier
  233. SubjectPublicKey asn1.BitString
  234. }
  235. // ComputeSKI derives an SKI from the certificate's public key in a
  236. // standard manner. This is done by computing the SHA-1 digest of the
  237. // SubjectPublicKeyInfo component of the certificate.
  238. func ComputeSKI(template *x509.Certificate) ([]byte, error) {
  239. pub := template.PublicKey
  240. encodedPub, err := x509.MarshalPKIXPublicKey(pub)
  241. if err != nil {
  242. return nil, err
  243. }
  244. var subPKI subjectPublicKeyInfo
  245. _, err = asn1.Unmarshal(encodedPub, &subPKI)
  246. if err != nil {
  247. return nil, err
  248. }
  249. pubHash := sha1.Sum(subPKI.SubjectPublicKey.Bytes)
  250. return pubHash[:], nil
  251. }
  252. // FillTemplate is a utility function that tries to load as much of
  253. // the certificate template as possible from the profiles and current
  254. // template. It fills in the key uses, expiration, revocation URLs
  255. // and SKI.
  256. func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.SigningProfile, notBefore time.Time, notAfter time.Time) error {
  257. ski, err := ComputeSKI(template)
  258. if err != nil {
  259. return err
  260. }
  261. var (
  262. eku []x509.ExtKeyUsage
  263. ku x509.KeyUsage
  264. backdate time.Duration
  265. expiry time.Duration
  266. crlURL, ocspURL string
  267. issuerURL = profile.IssuerURL
  268. )
  269. // The third value returned from Usages is a list of unknown key usages.
  270. // This should be used when validating the profile at load, and isn't used
  271. // here.
  272. ku, eku, _ = profile.Usages()
  273. if profile.IssuerURL == nil {
  274. issuerURL = defaultProfile.IssuerURL
  275. }
  276. if ku == 0 && len(eku) == 0 {
  277. return cferr.New(cferr.PolicyError, cferr.NoKeyUsages)
  278. }
  279. if expiry = profile.Expiry; expiry == 0 {
  280. expiry = defaultProfile.Expiry
  281. }
  282. if crlURL = profile.CRL; crlURL == "" {
  283. crlURL = defaultProfile.CRL
  284. }
  285. if ocspURL = profile.OCSP; ocspURL == "" {
  286. ocspURL = defaultProfile.OCSP
  287. }
  288. if notBefore.IsZero() {
  289. if !profile.NotBefore.IsZero() {
  290. notBefore = profile.NotBefore
  291. } else {
  292. if backdate = profile.Backdate; backdate == 0 {
  293. backdate = -5 * time.Minute
  294. } else {
  295. backdate = -1 * profile.Backdate
  296. }
  297. notBefore = time.Now().Round(time.Minute).Add(backdate)
  298. }
  299. }
  300. notBefore = notBefore.UTC()
  301. if notAfter.IsZero() {
  302. if !profile.NotAfter.IsZero() {
  303. notAfter = profile.NotAfter
  304. } else {
  305. notAfter = notBefore.Add(expiry)
  306. }
  307. }
  308. notAfter = notAfter.UTC()
  309. template.NotBefore = notBefore
  310. template.NotAfter = notAfter
  311. template.KeyUsage = ku
  312. template.ExtKeyUsage = eku
  313. template.BasicConstraintsValid = true
  314. template.IsCA = profile.CAConstraint.IsCA
  315. if template.IsCA {
  316. template.MaxPathLen = profile.CAConstraint.MaxPathLen
  317. if template.MaxPathLen == 0 {
  318. template.MaxPathLenZero = profile.CAConstraint.MaxPathLenZero
  319. }
  320. template.DNSNames = nil
  321. template.EmailAddresses = nil
  322. template.URIs = nil
  323. }
  324. template.SubjectKeyId = ski
  325. if ocspURL != "" {
  326. template.OCSPServer = []string{ocspURL}
  327. }
  328. if crlURL != "" {
  329. template.CRLDistributionPoints = []string{crlURL}
  330. }
  331. if len(issuerURL) != 0 {
  332. template.IssuingCertificateURL = issuerURL
  333. }
  334. if len(profile.Policies) != 0 {
  335. err = addPolicies(template, profile.Policies)
  336. if err != nil {
  337. return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
  338. }
  339. }
  340. if profile.OCSPNoCheck {
  341. ocspNoCheckExtension := pkix.Extension{
  342. Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5},
  343. Critical: false,
  344. Value: []byte{0x05, 0x00},
  345. }
  346. template.ExtraExtensions = append(template.ExtraExtensions, ocspNoCheckExtension)
  347. }
  348. return nil
  349. }
  350. type policyInformation struct {
  351. PolicyIdentifier asn1.ObjectIdentifier
  352. Qualifiers []interface{} `asn1:"tag:optional,omitempty"`
  353. }
  354. type cpsPolicyQualifier struct {
  355. PolicyQualifierID asn1.ObjectIdentifier
  356. Qualifier string `asn1:"tag:optional,ia5"`
  357. }
  358. type userNotice struct {
  359. ExplicitText string `asn1:"tag:optional,utf8"`
  360. }
  361. type userNoticePolicyQualifier struct {
  362. PolicyQualifierID asn1.ObjectIdentifier
  363. Qualifier userNotice
  364. }
  365. var (
  366. // Per https://tools.ietf.org/html/rfc3280.html#page-106, this represents:
  367. // iso(1) identified-organization(3) dod(6) internet(1) security(5)
  368. // mechanisms(5) pkix(7) id-qt(2) id-qt-cps(1)
  369. iDQTCertificationPracticeStatement = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1}
  370. // iso(1) identified-organization(3) dod(6) internet(1) security(5)
  371. // mechanisms(5) pkix(7) id-qt(2) id-qt-unotice(2)
  372. iDQTUserNotice = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2}
  373. // CTPoisonOID is the object ID of the critical poison extension for precertificates
  374. // https://tools.ietf.org/html/rfc6962#page-9
  375. CTPoisonOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3}
  376. // SCTListOID is the object ID for the Signed Certificate Timestamp certificate extension
  377. // https://tools.ietf.org/html/rfc6962#page-14
  378. SCTListOID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}
  379. )
  380. // addPolicies adds Certificate Policies and optional Policy Qualifiers to a
  381. // certificate, based on the input config. Go's x509 library allows setting
  382. // Certificate Policies easily, but does not support nested Policy Qualifiers
  383. // under those policies. So we need to construct the ASN.1 structure ourselves.
  384. func addPolicies(template *x509.Certificate, policies []config.CertificatePolicy) error {
  385. asn1PolicyList := []policyInformation{}
  386. for _, policy := range policies {
  387. pi := policyInformation{
  388. // The PolicyIdentifier is an OID assigned to a given issuer.
  389. PolicyIdentifier: asn1.ObjectIdentifier(policy.ID),
  390. }
  391. for _, qualifier := range policy.Qualifiers {
  392. switch qualifier.Type {
  393. case "id-qt-unotice":
  394. pi.Qualifiers = append(pi.Qualifiers,
  395. userNoticePolicyQualifier{
  396. PolicyQualifierID: iDQTUserNotice,
  397. Qualifier: userNotice{
  398. ExplicitText: qualifier.Value,
  399. },
  400. })
  401. case "id-qt-cps":
  402. pi.Qualifiers = append(pi.Qualifiers,
  403. cpsPolicyQualifier{
  404. PolicyQualifierID: iDQTCertificationPracticeStatement,
  405. Qualifier: qualifier.Value,
  406. })
  407. default:
  408. return errors.New("Invalid qualifier type in Policies " + qualifier.Type)
  409. }
  410. }
  411. asn1PolicyList = append(asn1PolicyList, pi)
  412. }
  413. asn1Bytes, err := asn1.Marshal(asn1PolicyList)
  414. if err != nil {
  415. return err
  416. }
  417. template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{
  418. Id: asn1.ObjectIdentifier{2, 5, 29, 32},
  419. Critical: false,
  420. Value: asn1Bytes,
  421. })
  422. return nil
  423. }