Skip to content

Commit c8104a1

Browse files
rolandshoemakergopherbot
authored andcommitted
[release-branch.go1.19] 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 #57427 Change-Id: Ib597ce202abb60702f730e75da583894422e4c14 Reviewed-on: https://go-review.googlesource.com/c/go/+/452620 Run-TryBot: Roland Shoemaker <[email protected]> Reviewed-by: Filippo Valsorda <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> (cherry picked from commit c9a10d4) Reviewed-on: https://go-review.googlesource.com/c/go/+/460895 Run-TryBot: Filippo Valsorda <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]> Auto-Submit: Heschi Kreinick <[email protected]> Reviewed-by: Carlos Amedee <[email protected]>
1 parent e04be8b commit c8104a1

File tree

5 files changed

+40
-12
lines changed

5 files changed

+40
-12
lines changed

src/crypto/x509/internal/macos/corefoundation.go

+7
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ func CFErrorCopyDescription(errRef CFRef) CFRef {
188188
}
189189
func x509_CFErrorCopyDescription_trampoline()
190190

191+
//go:cgo_import_dynamic x509_CFErrorGetCode CFErrorGetCode "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
192+
193+
func CFErrorGetCode(errRef CFRef) int {
194+
return int(syscall(abi.FuncPCABI0(x509_CFErrorGetCode_trampoline), uintptr(errRef), 0, 0, 0, 0, 0))
195+
}
196+
func x509_CFErrorGetCode_trampoline()
197+
191198
//go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
192199

193200
func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {

src/crypto/x509/internal/macos/corefoundation.s

+2
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,7 @@ TEXT ·x509_CFDataCreate_trampoline(SB),NOSPLIT,$0-0
3737
JMP x509_CFDataCreate(SB)
3838
TEXT ·x509_CFErrorCopyDescription_trampoline(SB),NOSPLIT,$0-0
3939
JMP x509_CFErrorCopyDescription(SB)
40+
TEXT ·x509_CFErrorGetCode_trampoline(SB),NOSPLIT,$0-0
41+
JMP x509_CFErrorGetCode(SB)
4042
TEXT ·x509_CFStringCreateExternalRepresentation_trampoline(SB),NOSPLIT,$0-0
4143
JMP x509_CFStringCreateExternalRepresentation(SB)

src/crypto/x509/internal/macos/security.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package macOS
88

99
import (
1010
"errors"
11-
"fmt"
1211
"internal/abi"
1312
"strconv"
1413
"unsafe"
@@ -52,6 +51,15 @@ const (
5251
SecTrustSettingsDomainSystem
5352
)
5453

54+
const (
55+
// various macOS error codes that can be returned from
56+
// SecTrustEvaluateWithError that we can map to Go cert
57+
// verification error types.
58+
ErrSecCertificateExpired = -67818
59+
ErrSecHostNameMismatch = -67602
60+
ErrSecNotTrusted = -67843
61+
)
62+
5563
type OSStatus struct {
5664
call string
5765
status int32
@@ -196,17 +204,18 @@ func x509_SecTrustGetResult_trampoline()
196204

197205
//go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security"
198206

199-
func SecTrustEvaluateWithError(trustObj CFRef) error {
207+
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
200208
var errRef CFRef
201209
ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0)
202210
if int32(ret) != 1 {
203211
errStr := CFErrorCopyDescription(errRef)
204-
err := fmt.Errorf("x509: %s", CFStringToString(errStr))
212+
err := errors.New(CFStringToString(errStr))
213+
errCode := CFErrorGetCode(errRef)
205214
CFRelease(errRef)
206215
CFRelease(errStr)
207-
return err
216+
return errCode, err
208217
}
209-
return nil
218+
return 0, nil
210219
}
211220
func x509_SecTrustEvaluateWithError_trampoline()
212221

src/crypto/x509/root_darwin.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package x509
77
import (
88
macOS "crypto/x509/internal/macos"
99
"errors"
10+
"fmt"
1011
)
1112

1213
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
@@ -54,8 +55,17 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
5455
// always enforce its SCT requirements, and there are still _some_ people
5556
// using TLS or OCSP for that.
5657

57-
if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
58-
return nil, err
58+
if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil {
59+
switch ret {
60+
case macOS.ErrSecCertificateExpired:
61+
return nil, CertificateInvalidError{c, Expired, err.Error()}
62+
case macOS.ErrSecHostNameMismatch:
63+
return nil, HostnameError{c, opts.DNSName}
64+
case macOS.ErrSecNotTrusted:
65+
return nil, UnknownAuthorityError{Cert: c}
66+
default:
67+
return nil, fmt.Errorf("x509: %s", err)
68+
}
5969
}
6070

6171
chain := [][]*Certificate{{}}

src/crypto/x509/root_darwin_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@ func TestPlatformVerifier(t *testing.T) {
4242
{
4343
name: "expired leaf",
4444
host: "expired.badssl.com",
45-
expectedErr: "x509: “*.badssl.com” certificate is expired",
45+
expectedErr: "x509: certificate has expired or is not yet valid: “*.badssl.com” certificate is expired",
4646
},
4747
{
4848
name: "wrong host for leaf",
4949
host: "wrong.host.badssl.com",
5050
verifyName: "wrong.host.badssl.com",
51-
expectedErr: "x509: *.badssl.com” certificate name does not match input",
51+
expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com",
5252
},
5353
{
5454
name: "self-signed leaf",
5555
host: "self-signed.badssl.com",
56-
expectedErr: "x509: “*.badssl.com” certificate is not trusted",
56+
expectedErr: "x509: certificate signed by unknown authority",
5757
},
5858
{
5959
name: "untrusted root",
6060
host: "untrusted-root.badssl.com",
61-
expectedErr: "x509: “BadSSL Untrusted Root Certificate Authority” certificate is not trusted",
61+
expectedErr: "x509: certificate signed by unknown authority",
6262
},
6363
{
6464
name: "revoked leaf",
@@ -74,7 +74,7 @@ func TestPlatformVerifier(t *testing.T) {
7474
name: "expired leaf (custom time)",
7575
host: "google.com",
7676
verifyTime: time.Time{}.Add(time.Hour),
77-
expectedErr: "x509: “*.google.com” certificate is expired",
77+
expectedErr: "x509: certificate has expired or is not yet valid: “*.google.com” certificate is expired",
7878
},
7979
{
8080
name: "valid chain (custom time)",

0 commit comments

Comments
 (0)