Commit a324a5ac authored by Mikkel Krautz's avatar Mikkel Krautz Committed by Adam Langley

crypto/x509: new home for root fetchers; build chains using Windows API

This moves the various CA root fetchers from crypto/tls into crypto/x509.

The move was brought about by issue 2997. Windows doesn't ship with all
its root certificates, but will instead download them as-needed when using
CryptoAPI for certificate verification.

This CL changes crypto/x509 to verify a certificate using the system root
CAs when VerifyOptions.RootCAs == nil. On Windows, this verification is
now implemented using Windows's CryptoAPI. All other root fetchers are
unchanged, and still use Go's own verification code.

The CL also fixes the hostname matching logic in crypto/tls/tls.go, in
order to be able to test whether hostname mismatches are honored by the
Windows verification code.

The move to crypto/x509 also allows other packages to use the OS-provided
root certificates, instead of hiding them inside the crypto/tls package.

Fixes #2997.

R=agl, golang-dev, alex.brainman, rsc, mikkel
CC=golang-dev
https://golang.org/cl/5700087
parent 807aadcd
......@@ -198,14 +198,6 @@ func (c *Config) time() time.Time {
return t()
}
func (c *Config) rootCAs() *x509.CertPool {
s := c.RootCAs
if s == nil {
s = defaultRoots()
}
return s
}
func (c *Config) cipherSuites() []uint16 {
s := c.CipherSuites
if s == nil {
......@@ -311,28 +303,16 @@ func defaultConfig() *Config {
return &emptyConfig
}
var once sync.Once
func defaultRoots() *x509.CertPool {
once.Do(initDefaults)
return varDefaultRoots
}
var (
once sync.Once
varDefaultCipherSuites []uint16
)
func defaultCipherSuites() []uint16 {
once.Do(initDefaults)
once.Do(initDefaultCipherSuites)
return varDefaultCipherSuites
}
func initDefaults() {
initDefaultRoots()
initDefaultCipherSuites()
}
var (
varDefaultRoots *x509.CertPool
varDefaultCipherSuites []uint16
)
func initDefaultCipherSuites() {
varDefaultCipherSuites = make([]uint16, len(cipherSuites))
for i, suite := range cipherSuites {
......
......@@ -102,7 +102,7 @@ func (c *Conn) clientHandshake() error {
if !c.config.InsecureSkipVerify {
opts := x509.VerifyOptions{
Roots: c.config.rootCAs(),
Roots: c.config.RootCAs,
CurrentTime: c.config.time(),
DNSName: c.config.ServerName,
Intermediates: x509.NewCertPool(),
......
......@@ -5,25 +5,25 @@
package tls
import (
"crypto/x509"
"runtime"
"testing"
)
var tlsServers = []string{
"google.com:443",
"github.com:443",
"twitter.com:443",
"google.com",
"github.com",
"twitter.com",
}
func TestOSCertBundles(t *testing.T) {
defaultRoots()
if testing.Short() {
t.Logf("skipping certificate tests in short mode")
return
}
for _, addr := range tlsServers {
conn, err := Dial("tcp", addr, nil)
conn, err := Dial("tcp", addr+":443", &Config{ServerName: addr})
if err != nil {
t.Errorf("unable to verify %v: %v", addr, err)
continue
......@@ -34,3 +34,28 @@ func TestOSCertBundles(t *testing.T) {
}
}
}
func TestCertHostnameVerifyWindows(t *testing.T) {
if runtime.GOOS != "windows" {
return
}
if testing.Short() {
t.Logf("skipping certificate tests in short mode")
return
}
for _, addr := range tlsServers {
cfg := &Config{ServerName: "example.com"}
conn, err := Dial("tcp", addr+":443", cfg)
if err == nil {
conn.Close()
t.Errorf("should fail to verify for example.com: %v", addr, err)
continue
}
_, ok := err.(x509.HostnameError)
if !ok {
t.Errorf("error type mismatch, got: %v", err)
}
}
}
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
"crypto/x509"
"syscall"
"unsafe"
)
func loadStore(roots *x509.CertPool, name string) {
store, err := syscall.CertOpenSystemStore(syscall.InvalidHandle, syscall.StringToUTF16Ptr(name))
if err != nil {
return
}
defer syscall.CertCloseStore(store, 0)
var cert *syscall.CertContext
for {
cert, err = syscall.CertEnumCertificatesInStore(store, cert)
if err != nil {
return
}
buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
// ParseCertificate requires its own copy of certificate data to keep.
buf2 := make([]byte, cert.Length)
copy(buf2, buf)
if c, err := x509.ParseCertificate(buf2); err == nil {
roots.AddCert(c)
}
}
}
func initDefaultRoots() {
roots := x509.NewCertPool()
// Roots
loadStore(roots, "ROOT")
// Intermediates
loadStore(roots, "CA")
varDefaultRoots = roots
}
......@@ -97,7 +97,9 @@ func Dial(network, addr string, config *Config) (*Conn, error) {
if config == nil {
config = defaultConfig()
}
if config.ServerName != "" {
// If no ServerName is set, infer the ServerName
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
c := *config
c.ServerName = hostname
......
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package x509
import "sync"
var (
once sync.Once
systemRoots *CertPool
)
func systemRootsPool() *CertPool {
once.Do(initSystemRoots)
return systemRoots
}
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
package x509
/*
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
......@@ -59,13 +59,14 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
}
*/
import "C"
import (
"crypto/x509"
"unsafe"
)
import "unsafe"
func initDefaultRoots() {
roots := x509.NewCertPool()
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
func initSystemRoots() {
roots := NewCertPool()
var data C.CFDataRef = nil
err := C.FetchPEMRoots(&data)
......@@ -75,5 +76,5 @@ func initDefaultRoots() {
roots.AppendCertsFromPEM(buf)
}
varDefaultRoots = roots
systemRoots = roots
}
......@@ -4,7 +4,12 @@
// +build plan9 darwin,!cgo
package tls
package x509
func initDefaultRoots() {
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
func initSystemRoots() {
systemRoots = NewCertPool()
}
......@@ -4,12 +4,9 @@
// +build freebsd linux openbsd netbsd
package tls
package x509
import (
"crypto/x509"
"io/ioutil"
)
import "io/ioutil"
// Possible certificate files; stop after finding one.
var certFiles = []string{
......@@ -20,8 +17,12 @@ var certFiles = []string{
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
}
func initDefaultRoots() {
roots := x509.NewCertPool()
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
func initSystemRoots() {
roots := NewCertPool()
for _, file := range certFiles {
data, err := ioutil.ReadFile(file)
if err == nil {
......@@ -29,5 +30,6 @@ func initDefaultRoots() {
break
}
}
varDefaultRoots = roots
systemRoots = roots
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package x509
import (
"syscall"
"unsafe"
)
// Creates a new *syscall.CertContext representing the leaf certificate in an in-memory
// certificate store containing itself and all of the intermediate certificates specified
// in the opts.Intermediates CertPool.
//
// A pointer to the in-memory store is available in the returned CertContext's Store field.
// The store is automatically freed when the CertContext is freed using
// syscall.CertFreeCertificateContext.
func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertContext, error) {
var storeCtx *syscall.CertContext
leafCtx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &leaf.Raw[0], uint32(len(leaf.Raw)))
if err != nil {
return nil, err
}
defer syscall.CertFreeCertificateContext(leafCtx)
handle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
if err != nil {
return nil, err
}
defer syscall.CertCloseStore(handle, 0)
err = syscall.CertAddCertificateContextToStore(handle, leafCtx, syscall.CERT_STORE_ADD_ALWAYS, &storeCtx)
if err != nil {
return nil, err
}
if opts.Intermediates != nil {
for _, intermediate := range opts.Intermediates.certs {
ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw)))
if err != nil {
return nil, err
}
err = syscall.CertAddCertificateContextToStore(handle, ctx, syscall.CERT_STORE_ADD_ALWAYS, nil)
if err != nil {
return nil, err
}
err = syscall.CertFreeCertificateContext(ctx)
if err != nil {
return nil, err
}
}
}
return storeCtx, nil
}
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
hasDNSName := opts != nil && len(opts.DNSName) > 0
storeCtx, err := createStoreContext(c, opts)
if err != nil {
return nil, err
}
defer syscall.CertFreeCertificateContext(storeCtx)
para := new(syscall.CertChainPara)
para.Size = uint32(unsafe.Sizeof(*para))
para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_AND
// If there's a DNSName set in opts, assume we're verifying
// a certificate from a TLS server.
if hasDNSName {
oids := []*byte{&syscall.OID_PKIX_KP_SERVER_AUTH[0]}
para.RequestedUsage.Usage.Length = uint32(len(oids))
para.RequestedUsage.Usage.UsageIdentifiers = &oids[0]
} else {
para.RequestedUsage.Usage.Length = 0
para.RequestedUsage.Usage.UsageIdentifiers = nil
}
var verifyTime *syscall.Filetime
if opts != nil && !opts.CurrentTime.IsZero() {
ft := syscall.NsecToFiletime(opts.CurrentTime.UnixNano())
verifyTime = &ft
}
// CertGetCertificateChain will traverse Windows's root stores
// in an attempt to build a verified certificate chain. Once
// it has found a verified chain, it stops. MSDN docs on
// CERT_CHAIN_CONTEXT:
//
// When a CERT_CHAIN_CONTEXT is built, the first simple chain
// begins with an end certificate and ends with a self-signed
// certificate. If that self-signed certificate is not a root
// or otherwise trusted certificate, an attempt is made to
// build a new chain. CTLs are used to create the new chain
// beginning with the self-signed certificate from the original
// chain as the end certificate of the new chain. This process
// continues building additional simple chains until the first
// self-signed certificate is a trusted certificate or until
// an additional simple chain cannot be built.
//
// The result is that we'll only get a single trusted chain to
// return to our caller.
var chainCtx *syscall.CertChainContext
err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, 0, 0, &chainCtx)
if err != nil {
return nil, err
}
defer syscall.CertFreeCertificateChain(chainCtx)
if chainCtx.TrustStatus.ErrorStatus != syscall.CERT_TRUST_NO_ERROR {
status := chainCtx.TrustStatus.ErrorStatus
switch status {
case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
return nil, CertificateInvalidError{c, Expired}
default:
return nil, UnknownAuthorityError{c}
}
}
simpleChains := (*[1 << 20]*syscall.CertSimpleChain)(unsafe.Pointer(chainCtx.Chains))[:]
if chainCtx.ChainCount == 0 {
return nil, UnknownAuthorityError{c}
}
verifiedChain := simpleChains[int(chainCtx.ChainCount)-1]
elements := (*[1 << 20]*syscall.CertChainElement)(unsafe.Pointer(verifiedChain.Elements))[:]
if verifiedChain.NumElements == 0 {
return nil, UnknownAuthorityError{c}
}
var chain []*Certificate
for i := 0; i < int(verifiedChain.NumElements); i++ {
// Copy the buf, since ParseCertificate does not create its own copy.
cert := elements[i].CertContext
encodedCert := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
buf := make([]byte, cert.Length)
copy(buf, encodedCert[:])
parsedCert, err := ParseCertificate(buf)
if err != nil {
return nil, err
}
chain = append(chain, parsedCert)
}
// Apply the system SSL policy if VerifyOptions dictates that we
// must check for a DNS name.
if hasDNSName {
sslPara := &syscall.SSLExtraCertChainPolicyPara{
AuthType: syscall.AUTHTYPE_SERVER,
ServerName: syscall.StringToUTF16Ptr(opts.DNSName),
}
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
para := &syscall.CertChainPolicyPara{
ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)),
}
para.Size = uint32(unsafe.Sizeof(*para))
status := syscall.CertChainPolicyStatus{}
err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
if err != nil {
return nil, err
}
if status.Error != 0 {
switch status.Error {
case syscall.CERT_E_EXPIRED:
return nil, CertificateInvalidError{c, Expired}
case syscall.CERT_E_CN_NO_MATCH:
return nil, HostnameError{c, opts.DNSName}
case syscall.CERT_E_UNTRUSTEDROOT:
return nil, UnknownAuthorityError{c}
default:
return nil, UnknownAuthorityError{c}
}
}
}
chains = make([][]*Certificate, 1)
chains[0] = chain
return chains, nil
}
func initSystemRoots() {
systemRoots = NewCertPool()
}
......@@ -5,6 +5,7 @@
package x509
import (
"runtime"
"strings"
"time"
"unicode/utf8"
......@@ -81,7 +82,7 @@ func (e UnknownAuthorityError) Error() string {
type VerifyOptions struct {
DNSName string
Intermediates *CertPool
Roots *CertPool
Roots *CertPool // if nil, the system roots are used
CurrentTime time.Time // if zero, the current time is used
}
......@@ -146,22 +147,33 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
// Verify attempts to verify c by building one or more chains from c to a
// certificate in opts.roots, using certificates in opts.Intermediates if
// certificate in opts.Roots, using certificates in opts.Intermediates if
// needed. If successful, it returns one or more chains where the first
// element of the chain is c and the last element is from opts.Roots.
//
// WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
// Use Windows's own verification and chain building.
if opts.Roots == nil && runtime.GOOS == "windows" {
return c.systemVerify(&opts)
}
if opts.Roots == nil {
opts.Roots = systemRootsPool()
}
err = c.isValid(leafCertificate, nil, &opts)
if err != nil {
return
}
if len(opts.DNSName) > 0 {
err = c.VerifyHostname(opts.DNSName)
if err != nil {
return
}
}
return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
}
......
......@@ -8,6 +8,7 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"errors"
"runtime"
"strings"
"testing"
"time"
......@@ -19,7 +20,7 @@ type verifyTest struct {
roots []string
currentTime int64
dnsName string
nilRoots bool
systemSkip bool
errorCallback func(*testing.T, int, error) bool
expectedChains [][]string
......@@ -57,14 +58,6 @@ var verifyTests = []verifyTest{
errorCallback: expectHostnameError,
},
{
leaf: googleLeaf,
intermediates: []string{thawteIntermediate},
nilRoots: true, // verifies that we don't crash
currentTime: 1302726541,
dnsName: "www.google.com",
errorCallback: expectAuthorityUnknown,
},
{
leaf: googleLeaf,
intermediates: []string{thawteIntermediate},
......@@ -80,6 +73,9 @@ var verifyTests = []verifyTest{
currentTime: 1302726541,
dnsName: "www.google.com",
// Skip when using systemVerify, since Windows
// *will* find the missing intermediate cert.
systemSkip: true,
errorCallback: expectAuthorityUnknown,
},
{
......@@ -109,6 +105,9 @@ var verifyTests = []verifyTest{
roots: []string{startComRoot},
currentTime: 1302726541,
// Skip when using systemVerify, since Windows
// can only return a single chain to us (for now).
systemSkip: true,
expectedChains: [][]string{
{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
......@@ -148,23 +147,26 @@ func certificateFromPEM(pemBytes string) (*Certificate, error) {
return ParseCertificate(block.Bytes)
}
func TestVerify(t *testing.T) {
func testVerify(t *testing.T, useSystemRoots bool) {
for i, test := range verifyTests {
if useSystemRoots && test.systemSkip {
continue
}
opts := VerifyOptions{
Roots: NewCertPool(),
Intermediates: NewCertPool(),
DNSName: test.dnsName,
CurrentTime: time.Unix(test.currentTime, 0),
}
if test.nilRoots {
opts.Roots = nil
}
for j, root := range test.roots {
ok := opts.Roots.AppendCertsFromPEM([]byte(root))
if !ok {
t.Errorf("#%d: failed to parse root #%d", i, j)
return
if !useSystemRoots {
opts.Roots = NewCertPool()
for j, root := range test.roots {
ok := opts.Roots.AppendCertsFromPEM([]byte(root))
if !ok {
t.Errorf("#%d: failed to parse root #%d", i, j)
return
}
}
}
......@@ -225,6 +227,19 @@ func TestVerify(t *testing.T) {
}
}
func TestGoVerify(t *testing.T) {
testVerify(t, false)
}
func TestSystemVerify(t *testing.T) {
if runtime.GOOS != "windows" {
t.Logf("skipping verify test using system APIs on %q", runtime.GOOS)
return
}
testVerify(t, true)
}
func chainToDebugString(chain []*Certificate) string {
var chainStr string
for _, cert := range chain {
......
......@@ -183,8 +183,15 @@ func NewCallback(fn interface{}) uintptr
//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore
//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain
//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain
//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext
//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext
//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
......
This diff is collapsed.
This diff is collapsed.
......@@ -208,6 +208,61 @@ const (
CRYPT_MACHINE_KEYSET = 0x00000020
CRYPT_SILENT = 0x00000040
CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x00000080
USAGE_MATCH_TYPE_AND = 0
USAGE_MATCH_TYPE_OR = 1
X509_ASN_ENCODING = 0x00000001
PKCS_7_ASN_ENCODING = 0x00010000
CERT_STORE_PROV_MEMORY = 2
CERT_STORE_ADD_ALWAYS = 4
CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004
CERT_TRUST_NO_ERROR = 0x00000000
CERT_TRUST_IS_NOT_TIME_VALID = 0x00000001
CERT_TRUST_IS_REVOKED = 0x00000004
CERT_TRUST_IS_NOT_SIGNATURE_VALID = 0x00000008
CERT_TRUST_IS_NOT_VALID_FOR_USAGE = 0x00000010
CERT_TRUST_IS_UNTRUSTED_ROOT = 0x00000020
CERT_TRUST_REVOCATION_STATUS_UNKNOWN = 0x00000040
CERT_TRUST_IS_CYCLIC = 0x00000080
CERT_TRUST_INVALID_EXTENSION = 0x00000100
CERT_TRUST_INVALID_POLICY_CONSTRAINTS = 0x00000200
CERT_TRUST_INVALID_BASIC_CONSTRAINTS = 0x00000400
CERT_TRUST_INVALID_NAME_CONSTRAINTS = 0x00000800
CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x00001000
CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x00002000
CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x00004000
CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT = 0x00008000
CERT_TRUST_IS_OFFLINE_REVOCATION = 0x01000000
CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY = 0x02000000
CERT_TRUST_IS_EXPLICIT_DISTRUST = 0x04000000
CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT = 0x08000000
CERT_CHAIN_POLICY_BASE = 1
CERT_CHAIN_POLICY_AUTHENTICODE = 2
CERT_CHAIN_POLICY_AUTHENTICODE_TS = 3
CERT_CHAIN_POLICY_SSL = 4
CERT_CHAIN_POLICY_BASIC_CONSTRAINTS = 5
CERT_CHAIN_POLICY_NT_AUTH = 6
CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7
CERT_CHAIN_POLICY_EV = 8
CERT_E_EXPIRED = 0x800B0101
CERT_E_ROLE = 0x800B0103
CERT_E_PURPOSE = 0x800B0106
CERT_E_UNTRUSTEDROOT = 0x800B0109
CERT_E_CN_NO_MATCH = 0x800B010F
AUTHTYPE_CLIENT = 1
AUTHTYPE_SERVER = 2
)
var (
OID_PKIX_KP_SERVER_AUTH = []byte("1.3.6.1.5.5.7.3.1" + string([]byte{0}))
)
// Invented values to support what package os expects.
......@@ -702,6 +757,93 @@ type CertContext struct {
Store Handle
}
type CertChainContext struct {
Size uint32
TrustStatus CertTrustStatus
ChainCount uint32
Chains **CertSimpleChain
LowerQualityChainCount uint32
LowerQualityChains **CertChainContext
HasRevocationFreshnessTime uint32
RevocationFreshnessTime uint32
}
type CertSimpleChain struct {
Size uint32
TrustStatus CertTrustStatus
NumElements uint32
Elements **CertChainElement
TrustListInfo uintptr
HasRevocationFreshnessTime uint32
RevocationFreshnessTime uint32
}
type CertChainElement struct {
Size uint32
CertContext *CertContext
TrustStatus CertTrustStatus
RevocationInfo *CertRevocationInfo
IssuanceUsage *CertEnhKeyUsage
ApplicationUsage *CertEnhKeyUsage
ExtendedErrorInfo *uint16
}
type CertRevocationInfo struct {
Size uint32
RevocationResult uint32
RevocationOid *byte
OidSpecificInfo uintptr
HasFreshnessTime uint32
FreshnessTime uint32
CrlInfo uintptr // *CertRevocationCrlInfo
}
type CertTrustStatus struct {
ErrorStatus uint32
InfoStatus uint32
}
type CertUsageMatch struct {
Type uint32
Usage CertEnhKeyUsage
}
type CertEnhKeyUsage struct {
Length uint32
UsageIdentifiers **byte
}
type CertChainPara struct {
Size uint32
RequestedUsage CertUsageMatch
RequstedIssuancePolicy CertUsageMatch
URLRetrievalTimeout uint32
CheckRevocationFreshnessTime uint32
RevocationFreshnessTime uint32
CacheResync *Filetime
}
type CertChainPolicyPara struct {
Size uint32
Flags uint32
ExtraPolicyPara uintptr
}
type SSLExtraCertChainPolicyPara struct {
Size uint32
AuthType uint32
Checks uint32
ServerName *uint16
}
type CertChainPolicyStatus struct {
Size uint32
Error uint32
ChainIndex uint32
ElementIndex uint32
ExtraPolicyStatus uintptr
}
const (
// do not reorder
HKEY_CLASSES_ROOT = 0x80000000 + iota
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment