mirror of
https://github.com/golang/go.git
synced 2025-12-28 06:34:04 +00:00
[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 c9a10d48a8)
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>
This commit is contained in:
parent
eeaf508d13
commit
476384ec7b
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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{{}}
|
||||
|
||||
@ -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)",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user