Skip to content

Commit 8ad70a5

Browse files
committed
crypto/x509: allow a leaf certificate to be specified directly as root.
In other systems, putting a leaf certificate in the root store works to express that exactly that certificate is acceptable. This change makes that work in Go too. Fixes #16763. Change-Id: I5c0a8dbc47aa631b23dd49061fb217ed8b0c719c Reviewed-on: https://go-review.googlesource.com/27393 Run-TryBot: Adam Langley <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent bcd54f6 commit 8ad70a5

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

src/crypto/x509/cert_pool.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package x509
66

77
import (
8+
"bytes"
89
"encoding/pem"
910
"errors"
1011
"runtime"
@@ -64,6 +65,21 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCer
6465
return
6566
}
6667

68+
func (s *CertPool) contains(cert *Certificate) bool {
69+
if s == nil {
70+
return false
71+
}
72+
73+
candidates := s.byName[string(cert.RawSubject)]
74+
for _, c := range candidates {
75+
if bytes.Equal(cert.Raw, s.certs[c].Raw) {
76+
return true
77+
}
78+
}
79+
80+
return false
81+
}
82+
6783
// AddCert adds a certificate to a pool.
6884
func (s *CertPool) AddCert(cert *Certificate) {
6985
if cert == nil {

src/crypto/x509/verify.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,13 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
262262
}
263263
}
264264

265-
candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
266-
if err != nil {
267-
return
265+
var candidateChains [][]*Certificate
266+
if opts.Roots.contains(c) {
267+
candidateChains = append(candidateChains, []*Certificate{c})
268+
} else {
269+
if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
270+
return nil, err
271+
}
268272
}
269273

270274
keyUsages := opts.KeyUsages

src/crypto/x509/verify_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,30 @@ var verifyTests = []verifyTest{
235235
},
236236
},
237237
},
238+
{
239+
// Putting a certificate as a root directly should work as a
240+
// way of saying “exactly this”.
241+
leaf: selfSigned,
242+
roots: []string{selfSigned},
243+
currentTime: 1471624472,
244+
dnsName: "foo.example",
245+
systemSkip: true,
246+
247+
expectedChains: [][]string{
248+
{"Acme Co"},
249+
},
250+
},
251+
{
252+
// Putting a certificate as a root directly should not skip
253+
// other checks however.
254+
leaf: selfSigned,
255+
roots: []string{selfSigned},
256+
currentTime: 1471624472,
257+
dnsName: "notfoo.example",
258+
systemSkip: true,
259+
260+
errorCallback: expectHostnameError,
261+
},
238262
}
239263

240264
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -1088,3 +1112,22 @@ Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
10881112
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
10891113
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
10901114
-----END CERTIFICATE-----`
1115+
1116+
const selfSigned = `-----BEGIN CERTIFICATE-----
1117+
MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw
1118+
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz
1119+
NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
1120+
ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP
1121+
pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF
1122+
w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D
1123+
WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY
1124+
YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO
1125+
NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF
1126+
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C
1127+
C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim
1128+
4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN
1129+
UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0
1130+
pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG
1131+
vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE
1132+
cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj
1133+
-----END CERTIFICATE-----`

0 commit comments

Comments
 (0)