Skip to content

Commit 05471e9

Browse files
mattnbradfitz
authored andcommitted
crypto/x509: implement SystemCertPool on Windows
Fixes #16736 Change-Id: I335d201e3f6738d838de3881087cb640fc7670e8 Reviewed-on: https://go-review.googlesource.com/30578 Run-TryBot: Brad Fitzpatrick <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 707a833 commit 05471e9

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

src/crypto/x509/cert_pool.go

-5
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ package x509
77
import (
88
"bytes"
99
"encoding/pem"
10-
"errors"
11-
"runtime"
1210
)
1311

1412
// CertPool is a set of certificates.
@@ -31,9 +29,6 @@ func NewCertPool() *CertPool {
3129
// Any mutations to the returned pool are not written to disk and do
3230
// not affect any other pool.
3331
func SystemCertPool() (*CertPool, error) {
34-
if runtime.GOOS == "windows" {
35-
return nil, errors.New("crypto/x509: system root pool is not available on Windows")
36-
}
3732
return loadSystemRoots()
3833
}
3934

src/crypto/x509/root_windows.go

+34-1
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,37 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
225225
return chains, nil
226226
}
227227

228-
func loadSystemRoots() (*CertPool, error) { return nil, nil }
228+
func loadSystemRoots() (*CertPool, error) {
229+
const CRYPT_E_NOT_FOUND = 0x80092004
230+
231+
store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
232+
if err != nil {
233+
return nil, err
234+
}
235+
defer syscall.CertCloseStore(store, 0)
236+
237+
roots := NewCertPool()
238+
var cert *syscall.CertContext
239+
for {
240+
cert, err = syscall.CertEnumCertificatesInStore(store, cert)
241+
if err != nil {
242+
if errno, ok := err.(syscall.Errno); ok {
243+
if errno == CRYPT_E_NOT_FOUND {
244+
break
245+
}
246+
}
247+
return nil, err
248+
}
249+
if cert == nil {
250+
break
251+
}
252+
// Copy the buf, since ParseCertificate does not create its own copy.
253+
buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
254+
buf2 := make([]byte, cert.Length)
255+
copy(buf2, buf)
256+
if c, err := ParseCertificate(buf2); err == nil {
257+
roots.AddCert(c)
258+
}
259+
}
260+
return roots, nil
261+
}

src/crypto/x509/x509_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -1457,3 +1457,10 @@ func TestMultipleRDN(t *testing.T) {
14571457
t.Errorf("got serial number of %q, but want %q", cert.Subject.SerialNumber, want)
14581458
}
14591459
}
1460+
1461+
func TestSystemCertPool(t *testing.T) {
1462+
_, err := SystemCertPool()
1463+
if err != nil {
1464+
t.Fatal(err)
1465+
}
1466+
}

0 commit comments

Comments
 (0)