### What version of Go are you using (`go version`)? <pre> $ go version go version go1.20 darwin/amd64 </pre> ### Does this issue reproduce with the latest release? Yes. ### What operating system and processor architecture are you using (`go env`)? <details><summary><code>go env</code> Output</summary><br><pre> $ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/me/Library/Caches/go-build" GOENV="/Users/me/Library/Application Support/go/env" GOEXE="" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/me/go/pkg/mod" GONOPROXY="redacted" GONOSUMDB="redacted" GOOS="darwin" GOPATH="/Users/me/go" GOPRIVATE="redacted" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GOVCS="" GOVERSION="go1.20" GCCGO="gccgo" GOAMD64="v1" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/dev/null" GOWORK="" CGO_CFLAGS="-O2 -g" CGO_CPPFLAGS="" CGO_CXXFLAGS="-O2 -g" CGO_FFLAGS="-O2 -g" CGO_LDFLAGS="-O2 -g" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vd/0rnst0yj2md0t7ss9__mr1540000gs/T/go-build2389605252=/tmp/go-build -gno-record-gcc-switches -fno-common" </pre></details> ### What did you do? Attempted to check errors for specific certificate issues in errors returned from `tls.Conn.Read()`. ### What did you expect to see? `error`s that could be unwrapped to expose child `error`s. ### What did you see instead? `error`s flattened to strings, so the only solution was to parse the error value. ---- I have an existing PR to wrap child errors rather than flatten them to strings: #58299. Here are some notes about each of those changes (as requested): ---- All of these would happen during the TLS client connection handshake: * src/crypto/tls/handshake_client_tls13.go:499 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * Private function `tls.verifyHandshakeSignature()` * `crypto/rsa.VerifyPKCS1v15()` * `crypto/rsa.VerifyPSS()` * Many of of its errors (currently) are from `errors.New()` or `fmt.Errorf()` with no wrapped errors or specific `error` types. * src/crypto/tls/handshake_client_tls13.go:610 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * `tls/Certificate.PrivateKey.(crypto.Signer).Sign()` (for client certificate) * src/crypto/tls/handshake_client.go:111 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * Reading the random source (`io.Reader`; default is `crypto/rand.Reader`) * src/crypto/tls/handshake_client.go:118 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * Reading the random source (`io.Reader`; default is `crypto/rand.Reader`) * src/crypto/tls/handshake_client.go:652 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * `io.Writer` failure on `tls.Config.KeyLogWriter`, if set (which it is not, by default) * src/crypto/tls/handshake_client.go:858 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * Error source: * `crypto/x509.ParseCertificate()` ---- All of these would happen during the TLS server connection handshake: * src/crypto/tls/ticket.go:137 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * `crypto/aes.NewCipher()` * src/crypto/tls/handshake_server_tls13.go:641 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * `tls/Certificate.PrivateKey.(crypto.Signer).Sign()` (for server certificate) * src/crypto/tls/handshake_server_tls13.go:844 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * Private function `tls.verifyHandshakeSignature()` * `crypto/rsa.VerifyPKCS1v15()` * `crypto/rsa.VerifyPSS()` * Many of of its errors (currently) are from `errors.New()` or `fmt.Errorf()` with no wrapped errors or specific `error` types. * src/crypto/tls/handshake_server.go:673 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * Private function `tls.verifyHandshakeSignature()` * `crypto/rsa.VerifyPKCS1v15()` * `crypto/rsa.VerifyPSS()` * Many of of its errors (currently) are from `errors.New()` or `fmt.Errorf()` with no wrapped errors or specific `error` types. * src/crypto/tls/handshake_server.go:810 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * `crypto/x509.ParseCertificate()` ---- * src/crypto/tls/key_agreement.go:235 * Returns from: * `crypto/tls.Conn.HandshakeContext()` (for server connections) * Error source: * `tls/Certificate.PrivateKey.(crypto.Signer).Sign()` (for server certificate) * src/crypto/tls/key_agreement.go:335 * Returns from: * `crypto/tls.Conn.Read()` (for client connections) * `crypto/tls.Conn.HandshakeContext()` (for client connections) * Error source: * Private function `tls.verifyHandshakeSignature()` * `crypto/rsa.VerifyPKCS1v15()` * `crypto/rsa.VerifyPSS()` * Many of of its errors (currently) are from `errors.New()` or `fmt.Errorf()` with no wrapped errors or specific `error` types. ---- * src/crypto/x509/x509.go:2026 * Returns from: * `crypto/x509.CreateCertificateRequest()` * Error source: * `encoding/asn1.Marshal()` * src/crypto/x509/sec1.go:93 * Returns from: * `crypto/x509.ParsePKCS8PrivateKey()` * Error source: * `encoding/asn1.Unmarshal()` * src/crypto/x509/pkcs8.go:50 * Returns from: * `crypto/x509.ParsePKCS8PrivateKey()` * Error source: * `crypto/x509.ParsePKCS1PrivateKey()` * src/crypto/x509/pkcs8.go:62 * Returns from: * `crypto/x509.ParsePKCS8PrivateKey()` * Error source: * Private function `x509.parseECPrivateKey()` * `encoding/asn1.Unmarshal()` * Many of of its errors (currently) are from `errors.New()` or `fmt.Errorf()` with no wrapped errors or specific `error` types. * src/crypto/x509/pkcs8.go:119 * Returns from: * `crypto/x509.MarshalPKCS8PrivateKey()` * Error source: * `encoding/asn1.Marshal()` * src/crypto/x509/pkcs8.go:128 * Returns from: * `crypto/x509.MarshalPKCS8PrivateKey()` * Error source: * Private function `marshalECPrivateKeyWithOID()` * `encoding/asn1.Marshal()` * An error from `errors.New()` with no specific `error` type. * src/crypto/x509/pkcs8.go:157 * Returns from: * `crypto/x509.MarshalPKCS8PrivateKey()` * Error source: * `encoding/asn1.Marshal()` * src/crypto/x509/pkcs8.go:166 * Returns from: * `crypto/x509.MarshalPKCS8PrivateKey()` * Error source: * `encoding/asn1.Marshal()` * src/crypto/x509/parser.go:538 * Returns from: * `crypto/x509.ParseCertificate()` * `crypto/x509.ParseCertificates()` * Error source: * Private function `isIA5String()` * An error from `errors.New()` with no specific `error` type. * src/crypto/x509/parser.go:580 * Returns from: * `crypto/x509.ParseCertificate()` * `crypto/x509.ParseCertificates()` * Error source: * Private function `isIA5String()` * An error from `errors.New()` with no specific `error` type. * src/crypto/x509/parser.go:604 * Returns from: * `crypto/x509.ParseCertificate()` * `crypto/x509.ParseCertificates()` * Error source: * Private function `isIA5String()` * An error from `errors.New()` with no specific `error` type. * src/crypto/x509/pem_decrypt.go:203 * Returns from: * `crypto/x509.EncryptPEMBlock()` * Error source: * Reading from the random source (`io.Reader`) provided to `x509.EncryptPEMBlock()`
What version of Go are you using (
go version)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env)?go envOutputWhat did you do?
Attempted to check errors for specific certificate issues in errors returned from
tls.Conn.Read().What did you expect to see?
errors that could be unwrapped to expose childerrors.What did you see instead?
errors flattened to strings, so the only solution was to parse the error value.I have an existing PR to wrap child errors rather than flatten them to strings: #58299.
Here are some notes about each of those changes (as requested):
All of these would happen during the TLS client connection handshake:
src/crypto/tls/handshake_client_tls13.go:499
crypto/tls.Conn.Read()(for client connections)tls.verifyHandshakeSignature()crypto/rsa.VerifyPKCS1v15()crypto/rsa.VerifyPSS()errors.New()orfmt.Errorf()with no wrapped errors or specificerrortypes.src/crypto/tls/handshake_client_tls13.go:610
crypto/tls.Conn.Read()(for client connections)tls/Certificate.PrivateKey.(crypto.Signer).Sign()(for client certificate)src/crypto/tls/handshake_client.go:111
crypto/tls.Conn.Read()(for client connections)io.Reader; default iscrypto/rand.Reader)src/crypto/tls/handshake_client.go:118
crypto/tls.Conn.Read()(for client connections)io.Reader; default iscrypto/rand.Reader)src/crypto/tls/handshake_client.go:652
crypto/tls.Conn.Read()(for client connections)io.Writerfailure ontls.Config.KeyLogWriter, if set (which it is not, by default)src/crypto/tls/handshake_client.go:858
crypto/tls.Conn.Read()(for client connections)crypto/x509.ParseCertificate()All of these would happen during the TLS server connection handshake:
src/crypto/tls/ticket.go:137
crypto/tls.Conn.HandshakeContext()(for server connections)crypto/aes.NewCipher()src/crypto/tls/handshake_server_tls13.go:641
crypto/tls.Conn.HandshakeContext()(for server connections)tls/Certificate.PrivateKey.(crypto.Signer).Sign()(for server certificate)src/crypto/tls/handshake_server_tls13.go:844
crypto/tls.Conn.HandshakeContext()(for server connections)tls.verifyHandshakeSignature()crypto/rsa.VerifyPKCS1v15()crypto/rsa.VerifyPSS()errors.New()orfmt.Errorf()with no wrapped errors or specificerrortypes.src/crypto/tls/handshake_server.go:673
crypto/tls.Conn.HandshakeContext()(for server connections)tls.verifyHandshakeSignature()crypto/rsa.VerifyPKCS1v15()crypto/rsa.VerifyPSS()errors.New()orfmt.Errorf()with no wrapped errors or specificerrortypes.src/crypto/tls/handshake_server.go:810
crypto/tls.Conn.HandshakeContext()(for server connections)crypto/x509.ParseCertificate()crypto/tls.Conn.HandshakeContext()(for server connections)tls/Certificate.PrivateKey.(crypto.Signer).Sign()(for server certificate)crypto/tls.Conn.Read()(for client connections)crypto/tls.Conn.HandshakeContext()(for client connections)tls.verifyHandshakeSignature()crypto/rsa.VerifyPKCS1v15()crypto/rsa.VerifyPSS()errors.New()orfmt.Errorf()with no wrapped errors or specificerrortypes.src/crypto/x509/x509.go:2026
crypto/x509.CreateCertificateRequest()encoding/asn1.Marshal()src/crypto/x509/sec1.go:93
crypto/x509.ParsePKCS8PrivateKey()encoding/asn1.Unmarshal()src/crypto/x509/pkcs8.go:50
crypto/x509.ParsePKCS8PrivateKey()crypto/x509.ParsePKCS1PrivateKey()src/crypto/x509/pkcs8.go:62
crypto/x509.ParsePKCS8PrivateKey()x509.parseECPrivateKey()encoding/asn1.Unmarshal()errors.New()orfmt.Errorf()with no wrapped errors or specificerrortypes.src/crypto/x509/pkcs8.go:119
crypto/x509.MarshalPKCS8PrivateKey()encoding/asn1.Marshal()src/crypto/x509/pkcs8.go:128
crypto/x509.MarshalPKCS8PrivateKey()marshalECPrivateKeyWithOID()encoding/asn1.Marshal()errors.New()with no specificerrortype.src/crypto/x509/pkcs8.go:157
crypto/x509.MarshalPKCS8PrivateKey()encoding/asn1.Marshal()src/crypto/x509/pkcs8.go:166
crypto/x509.MarshalPKCS8PrivateKey()encoding/asn1.Marshal()src/crypto/x509/parser.go:538
crypto/x509.ParseCertificate()crypto/x509.ParseCertificates()isIA5String()errors.New()with no specificerrortype.src/crypto/x509/parser.go:580
crypto/x509.ParseCertificate()crypto/x509.ParseCertificates()isIA5String()errors.New()with no specificerrortype.src/crypto/x509/parser.go:604
crypto/x509.ParseCertificate()crypto/x509.ParseCertificates()isIA5String()errors.New()with no specificerrortype.src/crypto/x509/pem_decrypt.go:203
crypto/x509.EncryptPEMBlock()io.Reader) provided tox509.EncryptPEMBlock()