diff --git a/13.go b/13.go index 5eb4162..9183787 100644 --- a/13.go +++ b/13.go @@ -8,8 +8,12 @@ import ( "crypto/hmac" "crypto/rsa" "crypto/subtle" + "encoding/hex" "errors" + "fmt" "io" + "os" + "runtime/debug" "golang_org/x/crypto/curve25519" ) @@ -333,3 +337,30 @@ func hkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L return hkdfExpand(hash, secret, hkdfLabel, L) } + +// QuietError is an error wrapper that prevents the verbose handshake log +// dump on errors. Exposed for use by GetCertificate. +type QuietError struct { + Err error +} + +func (e QuietError) Error() string { + return e.Err.Error() + " [quiet]" +} + +func (hs *serverHandshakeState) traceErr(err error) { + if err == nil { + return + } + if _, ok := err.(QuietError); ok { + return + } + if os.Getenv("TLSDEBUG") == "error" { + if hs != nil && hs.clientHello != nil { + os.Stderr.WriteString(hex.Dump(hs.clientHello.marshal())) + } else if err == io.EOF { + return // don't stack trace on EOF before CH + } + fmt.Fprintf(os.Stderr, "\n%s\n", debug.Stack()) + } +} diff --git a/conn.go b/conn.go index 61cfa72..8e916d9 100644 --- a/conn.go +++ b/conn.go @@ -156,10 +156,15 @@ type halfConn struct { // used to save allocating a new buffer for each MAC. inDigestBuf, outDigestBuf []byte + + traceErr func(error) } func (hc *halfConn) setErrorLocked(err error) error { hc.err = err + if hc.traceErr != nil { + hc.traceErr(err) + } return err } diff --git a/handshake_server.go b/handshake_server.go index a8e58d3..9ce3075 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -51,6 +51,9 @@ func (c *Conn) serverHandshake() error { hs := serverHandshakeState{ c: c, } + c.in.traceErr = hs.traceErr + c.out.traceErr = hs.traceErr + defer func() { c.in.traceErr, c.out.traceErr = nil, nil }() isResume, err := hs.readClientHello() if err != nil { return err @@ -265,6 +268,9 @@ Curves: hs.cert, err = c.config.getCertificate(hs.clientHelloInfo()) if err != nil { + if _, ok := err.(QuietError); ok { + c.out.traceErr, c.in.traceErr = nil, nil + } c.sendAlert(alertInternalError) return false, err }