verify.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package x509
  5. import (
  6. "fmt"
  7. "net"
  8. "runtime"
  9. "strings"
  10. "time"
  11. "unicode/utf8"
  12. )
  13. type InvalidReason int
  14. const (
  15. // NotAuthorizedToSign results when a certificate is signed by another
  16. // which isn't marked as a CA certificate.
  17. NotAuthorizedToSign InvalidReason = iota
  18. // Expired results when a certificate has expired, based on the time
  19. // given in the VerifyOptions.
  20. Expired
  21. // CANotAuthorizedForThisName results when an intermediate or root
  22. // certificate has a name constraint which doesn't include the name
  23. // being checked.
  24. CANotAuthorizedForThisName
  25. // TooManyIntermediates results when a path length constraint is
  26. // violated.
  27. TooManyIntermediates
  28. // IncompatibleUsage results when the certificate's key usage indicates
  29. // that it may only be used for a different purpose.
  30. IncompatibleUsage
  31. )
  32. // CertificateInvalidError results when an odd error occurs. Users of this
  33. // library probably want to handle all these errors uniformly.
  34. type CertificateInvalidError struct {
  35. Cert *Certificate
  36. Reason InvalidReason
  37. }
  38. func (e CertificateInvalidError) Error() string {
  39. switch e.Reason {
  40. case NotAuthorizedToSign:
  41. return "x509: certificate is not authorized to sign other certificates"
  42. case Expired:
  43. return "x509: certificate has expired or is not yet valid"
  44. case CANotAuthorizedForThisName:
  45. return "x509: a root or intermediate certificate is not authorized to sign in this domain"
  46. case TooManyIntermediates:
  47. return "x509: too many intermediates for path length constraint"
  48. case IncompatibleUsage:
  49. return "x509: certificate specifies an incompatible key usage"
  50. }
  51. return "x509: unknown error"
  52. }
  53. // HostnameError results when the set of authorized names doesn't match the
  54. // requested name.
  55. type HostnameError struct {
  56. Certificate *Certificate
  57. Host string
  58. }
  59. func (h HostnameError) Error() string {
  60. c := h.Certificate
  61. var valid string
  62. if ip := net.ParseIP(h.Host); ip != nil {
  63. // Trying to validate an IP
  64. if len(c.IPAddresses) == 0 {
  65. return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
  66. }
  67. for _, san := range c.IPAddresses {
  68. if len(valid) > 0 {
  69. valid += ", "
  70. }
  71. valid += san.String()
  72. }
  73. } else {
  74. if len(c.DNSNames) > 0 {
  75. valid = strings.Join(c.DNSNames, ", ")
  76. } else {
  77. valid = c.Subject.CommonName
  78. }
  79. }
  80. return "x509: certificate is valid for " + valid + ", not " + h.Host
  81. }
  82. // UnknownAuthorityError results when the certificate issuer is unknown
  83. type UnknownAuthorityError struct {
  84. cert *Certificate
  85. // hintErr contains an error that may be helpful in determining why an
  86. // authority wasn't found.
  87. hintErr error
  88. // hintCert contains a possible authority certificate that was rejected
  89. // because of the error in hintErr.
  90. hintCert *Certificate
  91. }
  92. func (e UnknownAuthorityError) Error() string {
  93. s := "x509: certificate signed by unknown authority"
  94. if e.hintErr != nil {
  95. certName := e.hintCert.Subject.CommonName
  96. if len(certName) == 0 {
  97. if len(e.hintCert.Subject.Organization) > 0 {
  98. certName = e.hintCert.Subject.Organization[0]
  99. }
  100. certName = "serial:" + e.hintCert.SerialNumber.String()
  101. }
  102. s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
  103. }
  104. return s
  105. }
  106. // SystemRootsError results when we fail to load the system root certificates.
  107. type SystemRootsError struct {
  108. }
  109. func (e SystemRootsError) Error() string {
  110. return "x509: failed to load system roots and no roots provided"
  111. }
  112. // VerifyOptions contains parameters for Certificate.Verify. It's a structure
  113. // because other PKIX verification APIs have ended up needing many options.
  114. type VerifyOptions struct {
  115. DNSName string
  116. Intermediates *CertPool
  117. Roots *CertPool // if nil, the system roots are used
  118. CurrentTime time.Time // if zero, the current time is used
  119. DisableTimeChecks bool
  120. // KeyUsage specifies which Extended Key Usage values are acceptable.
  121. // An empty list means ExtKeyUsageServerAuth. Key usage is considered a
  122. // constraint down the chain which mirrors Windows CryptoAPI behaviour,
  123. // but not the spec. To accept any key usage, include ExtKeyUsageAny.
  124. KeyUsages []ExtKeyUsage
  125. }
  126. const (
  127. leafCertificate = iota
  128. intermediateCertificate
  129. rootCertificate
  130. )
  131. // isValid performs validity checks on the c.
  132. func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
  133. if !opts.DisableTimeChecks {
  134. now := opts.CurrentTime
  135. if now.IsZero() {
  136. now = time.Now()
  137. }
  138. if now.Before(c.NotBefore) || now.After(c.NotAfter) {
  139. return CertificateInvalidError{c, Expired}
  140. }
  141. }
  142. if len(c.PermittedDNSDomains) > 0 {
  143. ok := false
  144. for _, domain := range c.PermittedDNSDomains {
  145. if opts.DNSName == domain ||
  146. (strings.HasSuffix(opts.DNSName, domain) &&
  147. len(opts.DNSName) >= 1+len(domain) &&
  148. opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
  149. ok = true
  150. break
  151. }
  152. }
  153. if !ok {
  154. return CertificateInvalidError{c, CANotAuthorizedForThisName}
  155. }
  156. }
  157. // KeyUsage status flags are ignored. From Engineering Security, Peter
  158. // Gutmann: A European government CA marked its signing certificates as
  159. // being valid for encryption only, but no-one noticed. Another
  160. // European CA marked its signature keys as not being valid for
  161. // signatures. A different CA marked its own trusted root certificate
  162. // as being invalid for certificate signing. Another national CA
  163. // distributed a certificate to be used to encrypt data for the
  164. // country’s tax authority that was marked as only being usable for
  165. // digital signatures but not for encryption. Yet another CA reversed
  166. // the order of the bit flags in the keyUsage due to confusion over
  167. // encoding endianness, essentially setting a random keyUsage in
  168. // certificates that it issued. Another CA created a self-invalidating
  169. // certificate by adding a certificate policy statement stipulating
  170. // that the certificate had to be used strictly as specified in the
  171. // keyUsage, and a keyUsage containing a flag indicating that the RSA
  172. // encryption key could only be used for Diffie-Hellman key agreement.
  173. if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
  174. return CertificateInvalidError{c, NotAuthorizedToSign}
  175. }
  176. if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
  177. numIntermediates := len(currentChain) - 1
  178. if numIntermediates > c.MaxPathLen {
  179. return CertificateInvalidError{c, TooManyIntermediates}
  180. }
  181. }
  182. return nil
  183. }
  184. // Verify attempts to verify c by building one or more chains from c to a
  185. // certificate in opts.Roots, using certificates in opts.Intermediates if
  186. // needed. If successful, it returns one or more chains where the first
  187. // element of the chain is c and the last element is from opts.Roots.
  188. //
  189. // WARNING: this doesn't do any revocation checking.
  190. func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
  191. // Use Windows's own verification and chain building.
  192. if opts.Roots == nil && runtime.GOOS == "windows" {
  193. return c.systemVerify(&opts)
  194. }
  195. if opts.Roots == nil {
  196. opts.Roots = systemRootsPool()
  197. if opts.Roots == nil {
  198. return nil, SystemRootsError{}
  199. }
  200. }
  201. err = c.isValid(leafCertificate, nil, &opts)
  202. if err != nil {
  203. return
  204. }
  205. if len(opts.DNSName) > 0 {
  206. err = c.VerifyHostname(opts.DNSName)
  207. if err != nil {
  208. return
  209. }
  210. }
  211. candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
  212. if err != nil {
  213. return
  214. }
  215. keyUsages := opts.KeyUsages
  216. if len(keyUsages) == 0 {
  217. keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
  218. }
  219. // If any key usage is acceptable then we're done.
  220. for _, usage := range keyUsages {
  221. if usage == ExtKeyUsageAny {
  222. chains = candidateChains
  223. return
  224. }
  225. }
  226. for _, candidate := range candidateChains {
  227. if checkChainForKeyUsage(candidate, keyUsages) {
  228. chains = append(chains, candidate)
  229. }
  230. }
  231. if len(chains) == 0 {
  232. err = CertificateInvalidError{c, IncompatibleUsage}
  233. }
  234. return
  235. }
  236. func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
  237. n := make([]*Certificate, len(chain)+1)
  238. copy(n, chain)
  239. n[len(chain)] = cert
  240. return n
  241. }
  242. func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
  243. possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
  244. for _, rootNum := range possibleRoots {
  245. root := opts.Roots.certs[rootNum]
  246. err = root.isValid(rootCertificate, currentChain, opts)
  247. if err != nil {
  248. continue
  249. }
  250. chains = append(chains, appendToFreshChain(currentChain, root))
  251. }
  252. possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
  253. nextIntermediate:
  254. for _, intermediateNum := range possibleIntermediates {
  255. intermediate := opts.Intermediates.certs[intermediateNum]
  256. for _, cert := range currentChain {
  257. if cert == intermediate {
  258. continue nextIntermediate
  259. }
  260. }
  261. err = intermediate.isValid(intermediateCertificate, currentChain, opts)
  262. if err != nil {
  263. continue
  264. }
  265. var childChains [][]*Certificate
  266. childChains, ok := cache[intermediateNum]
  267. if !ok {
  268. childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
  269. cache[intermediateNum] = childChains
  270. }
  271. chains = append(chains, childChains...)
  272. }
  273. if len(chains) > 0 {
  274. err = nil
  275. }
  276. if len(chains) == 0 && err == nil {
  277. hintErr := rootErr
  278. hintCert := failedRoot
  279. if hintErr == nil {
  280. hintErr = intermediateErr
  281. hintCert = failedIntermediate
  282. }
  283. err = UnknownAuthorityError{c, hintErr, hintCert}
  284. }
  285. return
  286. }
  287. func matchHostnames(pattern, host string) bool {
  288. if len(pattern) == 0 || len(host) == 0 {
  289. return false
  290. }
  291. patternParts := strings.Split(pattern, ".")
  292. hostParts := strings.Split(host, ".")
  293. if len(patternParts) != len(hostParts) {
  294. return false
  295. }
  296. for i, patternPart := range patternParts {
  297. if patternPart == "*" {
  298. continue
  299. }
  300. if patternPart != hostParts[i] {
  301. return false
  302. }
  303. }
  304. return true
  305. }
  306. // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
  307. // an explicitly ASCII function to avoid any sharp corners resulting from
  308. // performing Unicode operations on DNS labels.
  309. func toLowerCaseASCII(in string) string {
  310. // If the string is already lower-case then there's nothing to do.
  311. isAlreadyLowerCase := true
  312. for _, c := range in {
  313. if c == utf8.RuneError {
  314. // If we get a UTF-8 error then there might be
  315. // upper-case ASCII bytes in the invalid sequence.
  316. isAlreadyLowerCase = false
  317. break
  318. }
  319. if 'A' <= c && c <= 'Z' {
  320. isAlreadyLowerCase = false
  321. break
  322. }
  323. }
  324. if isAlreadyLowerCase {
  325. return in
  326. }
  327. out := []byte(in)
  328. for i, c := range out {
  329. if 'A' <= c && c <= 'Z' {
  330. out[i] += 'a' - 'A'
  331. }
  332. }
  333. return string(out)
  334. }
  335. // VerifyHostname returns nil if c is a valid certificate for the named host.
  336. // Otherwise it returns an error describing the mismatch.
  337. func (c *Certificate) VerifyHostname(h string) error {
  338. // IP addresses may be written in [ ].
  339. candidateIP := h
  340. if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
  341. candidateIP = h[1 : len(h)-1]
  342. }
  343. if ip := net.ParseIP(candidateIP); ip != nil {
  344. // We only match IP addresses against IP SANs.
  345. // https://tools.ietf.org/html/rfc6125#appendix-B.2
  346. for _, candidate := range c.IPAddresses {
  347. if ip.Equal(candidate) {
  348. return nil
  349. }
  350. }
  351. return HostnameError{c, candidateIP}
  352. }
  353. lowered := toLowerCaseASCII(h)
  354. if len(c.DNSNames) > 0 {
  355. for _, match := range c.DNSNames {
  356. if matchHostnames(toLowerCaseASCII(match), lowered) {
  357. return nil
  358. }
  359. }
  360. // If Subject Alt Name is given, we ignore the common name.
  361. } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
  362. return nil
  363. }
  364. return HostnameError{c, h}
  365. }
  366. func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
  367. usages := make([]ExtKeyUsage, len(keyUsages))
  368. copy(usages, keyUsages)
  369. if len(chain) == 0 {
  370. return false
  371. }
  372. usagesRemaining := len(usages)
  373. // We walk down the list and cross out any usages that aren't supported
  374. // by each certificate. If we cross out all the usages, then the chain
  375. // is unacceptable.
  376. for i := len(chain) - 1; i >= 0; i-- {
  377. cert := chain[i]
  378. if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
  379. // The certificate doesn't have any extended key usage specified.
  380. continue
  381. }
  382. for _, usage := range cert.ExtKeyUsage {
  383. if usage == ExtKeyUsageAny {
  384. // The certificate is explicitly good for any usage.
  385. continue
  386. }
  387. }
  388. const invalidUsage ExtKeyUsage = -1
  389. NextRequestedUsage:
  390. for i, requestedUsage := range usages {
  391. if requestedUsage == invalidUsage {
  392. continue
  393. }
  394. for _, usage := range cert.ExtKeyUsage {
  395. if requestedUsage == usage {
  396. continue NextRequestedUsage
  397. } else if requestedUsage == ExtKeyUsageServerAuth &&
  398. (usage == ExtKeyUsageNetscapeServerGatedCrypto ||
  399. usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
  400. // In order to support COMODO
  401. // certificate chains, we have to
  402. // accept Netscape or Microsoft SGC
  403. // usages as equal to ServerAuth.
  404. continue NextRequestedUsage
  405. }
  406. }
  407. usages[i] = invalidUsage
  408. usagesRemaining--
  409. if usagesRemaining == 0 {
  410. return false
  411. }
  412. }
  413. }
  414. return true
  415. }