aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Shoemaker <roland@golang.org>2022-11-21 16:47:39 -0800
committerGopher Robot <gobot@golang.org>2023-01-06 17:52:13 +0000
commit476384ec7b6e4770ab25a754f656da9d8115cb66 (patch)
treeb06a4fcdd70471fcbd41e0166d213b9f9773ce9b
parenteeaf508d13b463c0bd2224275e239c01e06f4ade (diff)
downloadgo-476384ec7b6e4770ab25a754f656da9d8115cb66.tar.gz
go-476384ec7b6e4770ab25a754f656da9d8115cb66.zip
[release-branch.go1.18] crypto/x509: return typed verification errors on macOS
On macOS return the error code from SecTrustEvaluateWithError, and use it to create typed errors that can be returned from Verify. Updates #56891 Fixes #57426 Change-Id: Ib597ce202abb60702f730e75da583894422e4c14 Reviewed-on: https://go-review.googlesource.com/c/go/+/452620 Run-TryBot: Roland Shoemaker <roland@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> (cherry picked from commit c9a10d48a8f0e8479f5b9d98c5bd81b64a90d23d) Reviewed-on: https://go-review.googlesource.com/c/go/+/460896 Reviewed-by: Carlos Amedee <carlos@golang.org> Auto-Submit: Heschi Kreinick <heschi@google.com> Reviewed-by: Heschi Kreinick <heschi@google.com> Run-TryBot: Filippo Valsorda <filippo@golang.org>
-rw-r--r--src/crypto/x509/internal/macos/corefoundation.go7
-rw-r--r--src/crypto/x509/internal/macos/corefoundation.s2
-rw-r--r--src/crypto/x509/internal/macos/security.go19
-rw-r--r--src/crypto/x509/root_darwin.go14
-rw-r--r--src/crypto/x509/root_darwin_test.go10
5 files changed, 40 insertions, 12 deletions
diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go
index 75c212910b..2b20b52dc6 100644
--- a/src/crypto/x509/internal/macos/corefoundation.go
+++ b/src/crypto/x509/internal/macos/corefoundation.go
@@ -184,6 +184,13 @@ func CFErrorCopyDescription(errRef CFRef) CFRef {
}
func x509_CFErrorCopyDescription_trampoline()
+//go:cgo_import_dynamic x509_CFErrorGetCode CFErrorGetCode "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
+
+func CFErrorGetCode(errRef CFRef) int {
+ return int(syscall(abi.FuncPCABI0(x509_CFErrorGetCode_trampoline), uintptr(errRef), 0, 0, 0, 0, 0))
+}
+func x509_CFErrorGetCode_trampoline()
+
//go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
func CFStringCreateExternalRepresentation(strRef CFRef) CFRef {
diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s
index d69f72f795..49cd084467 100644
--- a/src/crypto/x509/internal/macos/corefoundation.s
+++ b/src/crypto/x509/internal/macos/corefoundation.s
@@ -37,5 +37,7 @@ TEXT ·x509_CFDataCreate_trampoline(SB),NOSPLIT,$0-0
JMP x509_CFDataCreate(SB)
TEXT ·x509_CFErrorCopyDescription_trampoline(SB),NOSPLIT,$0-0
JMP x509_CFErrorCopyDescription(SB)
+TEXT ·x509_CFErrorGetCode_trampoline(SB),NOSPLIT,$0-0
+ JMP x509_CFErrorGetCode(SB)
TEXT ·x509_CFStringCreateExternalRepresentation_trampoline(SB),NOSPLIT,$0-0
JMP x509_CFStringCreateExternalRepresentation(SB)
diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go
index ef64bda49f..0b7958eaa2 100644
--- a/src/crypto/x509/internal/macos/security.go
+++ b/src/crypto/x509/internal/macos/security.go
@@ -8,7 +8,6 @@ package macOS
import (
"errors"
- "fmt"
"internal/abi"
"strconv"
"unsafe"
@@ -51,6 +50,15 @@ const (
SecTrustSettingsDomainSystem
)
+const (
+ // various macOS error codes that can be returned from
+ // SecTrustEvaluateWithError that we can map to Go cert
+ // verification error types.
+ ErrSecCertificateExpired = -67818
+ ErrSecHostNameMismatch = -67602
+ ErrSecNotTrusted = -67843
+)
+
type OSStatus struct {
call string
status int32
@@ -190,17 +198,18 @@ func x509_SecTrustGetResult_trampoline()
//go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security"
-func SecTrustEvaluateWithError(trustObj CFRef) error {
+func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
var errRef CFRef
ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0)
if int32(ret) != 1 {
errStr := CFErrorCopyDescription(errRef)
- err := fmt.Errorf("x509: %s", CFStringToString(errStr))
+ err := errors.New(CFStringToString(errStr))
+ errCode := CFErrorGetCode(errRef)
CFRelease(errRef)
CFRelease(errStr)
- return err
+ return errCode, err
}
- return nil
+ return 0, nil
}
func x509_SecTrustEvaluateWithError_trampoline()
diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go
index ad365f577e..c35885ace8 100644
--- a/src/crypto/x509/root_darwin.go
+++ b/src/crypto/x509/root_darwin.go
@@ -7,6 +7,7 @@ package x509
import (
macOS "crypto/x509/internal/macos"
"errors"
+ "fmt"
)
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
@@ -54,8 +55,17 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
// always enforce its SCT requirements, and there are still _some_ people
// using TLS or OCSP for that.
- if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
- return nil, err
+ if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
+ switch ret {
+ case macOS.ErrSecCertificateExpired:
+ return nil, CertificateInvalidError{c, Expired, err.Error()}
+ case macOS.ErrSecHostNameMismatch:
+ return nil, HostnameError{c, opts.DNSName}
+ case macOS.ErrSecNotTrusted:
+ return nil, UnknownAuthorityError{Cert: c}
+ default:
+ return nil, fmt.Errorf("x509: %s", err)
+ }
}
chain := [][]*Certificate{{}}
diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go
index 90a464f624..299cecf556 100644
--- a/src/crypto/x509/root_darwin_test.go
+++ b/src/crypto/x509/root_darwin_test.go
@@ -42,23 +42,23 @@ func TestPlatformVerifier(t *testing.T) {
{
name: "expired leaf",
host: "expired.badssl.com",
- expectedErr: "x509: “*.badssl.com” certificate is expired",
+ expectedErr: "x509: certificate has expired or is not yet valid: “*.badssl.com” certificate is expired",
},
{
name: "wrong host for leaf",
host: "wrong.host.badssl.com",
verifyName: "wrong.host.badssl.com",
- expectedErr: "x509: “*.badssl.com” certificate name does not match input",
+ expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com",
},
{
name: "self-signed leaf",
host: "self-signed.badssl.com",
- expectedErr: "x509: “*.badssl.com” certificate is not trusted",
+ expectedErr: "x509: certificate signed by unknown authority",
},
{
name: "untrusted root",
host: "untrusted-root.badssl.com",
- expectedErr: "x509: “BadSSL Untrusted Root Certificate Authority” certificate is not trusted",
+ expectedErr: "x509: certificate signed by unknown authority",
},
{
name: "revoked leaf",
@@ -74,7 +74,7 @@ func TestPlatformVerifier(t *testing.T) {
name: "expired leaf (custom time)",
host: "google.com",
verifyTime: time.Time{}.Add(time.Hour),
- expectedErr: "x509: “*.google.com” certificate is expired",
+ expectedErr: "x509: certificate has expired or is not yet valid: “*.google.com” certificate is expired",
},
{
name: "valid chain (custom time)",