aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/x509/root_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/x509/root_windows.go')
-rw-r--r--src/crypto/x509/root_windows.go46
1 files changed, 33 insertions, 13 deletions
diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go
index ebf159c178..94669f229e 100644
--- a/src/crypto/x509/root_windows.go
+++ b/src/crypto/x509/root_windows.go
@@ -88,6 +88,9 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
switch status {
case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
return CertificateInvalidError{c, Expired, ""}
+ case syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE:
+ return CertificateInvalidError{c, IncompatibleUsage, ""}
+ // TODO(filippo): surface more error statuses.
default:
return UnknownAuthorityError{c, nil, nil}
}
@@ -138,11 +141,19 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
return nil
}
+// windowsExtKeyUsageOIDs are the C NUL-terminated string representations of the
+// OIDs for use with the Windows API.
+var windowsExtKeyUsageOIDs = make(map[ExtKeyUsage][]byte, len(extKeyUsageOIDs))
+
+func init() {
+ for _, eku := range extKeyUsageOIDs {
+ windowsExtKeyUsageOIDs[eku.extKeyUsage] = []byte(eku.oid.String() + "\x00")
+ }
+}
+
// systemVerify is like Verify, except that it uses CryptoAPI calls
// to build certificate chains and verify them.
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
@@ -152,17 +163,26 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
para := new(syscall.CertChainPara)
para.Size = uint32(unsafe.Sizeof(*para))
- // 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],
- // Both IE and Chrome allow certificates with
- // Server Gated Crypto as well. Some certificates
- // in the wild require them.
- &syscall.OID_SERVER_GATED_CRYPTO[0],
- &syscall.OID_SGC_NETSCAPE[0],
+ keyUsages := opts.KeyUsages
+ if len(keyUsages) == 0 {
+ keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
+ }
+ oids := make([]*byte, 0, len(keyUsages))
+ for _, eku := range keyUsages {
+ if eku == ExtKeyUsageAny {
+ oids = nil
+ break
+ }
+ if oid, ok := windowsExtKeyUsageOIDs[eku]; ok {
+ oids = append(oids, &oid[0])
}
+ // Like the standard verifier, accept SGC EKUs as equivalent to ServerAuth.
+ if eku == ExtKeyUsageServerAuth {
+ oids = append(oids, &syscall.OID_SERVER_GATED_CRYPTO[0])
+ oids = append(oids, &syscall.OID_SGC_NETSCAPE[0])
+ }
+ }
+ if oids != nil {
para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR
para.RequestedUsage.Usage.Length = uint32(len(oids))
para.RequestedUsage.Usage.UsageIdentifiers = &oids[0]
@@ -208,7 +228,7 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
return nil, err
}
- if hasDNSName {
+ if opts != nil && len(opts.DNSName) > 0 {
err = checkChainSSLServerPolicy(c, chainCtx, opts)
if err != nil {
return nil, err