1

I am trying around with mTls and go. I do not really understand how I got tls errors during the handshake on the client side. See the following example:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "strconv"
    "sync"
)

const CRT = "-----BEGIN CERTIFICATE-----\nMIIDHzCCAgegAwIBAgIGAYbbjzNfMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNVBAMM\nCTEyNy4wLjAuMTAeFw0yMzAzMTMxNTIwNDBaFw0yNDAzMTMxNTIwNDBaMBQxEjAQ\nBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAIlfhPzb31DD3ntWPLU2HSqb0z0dkns5hNQt3EN907wT2H+wnhPu9W21nOrQNk6D\nRPfs+2qzpuzMzbC1AAEz/YFrgctUgc7IDlMWOhmKusROb/VA4596jtIQpu35gUnO\niZ16V4ufUEGMn2ZNOB1FTlp+vTOjDvcEgXyEvwTrHjBAKf7/h8Ab8yQrEMZJLjNy\nUrC8IBtUKGr0qcYSBnbT35Y6weT0prZUi21trBQNtQQtegKnN3AssZnkUar3oc1M\nPSfEO385QbTj5P0RV6lYCdNNzlzZiyf89qdK1GwqjWIC5NMEfhgCWBmdwo4SHUUo\nPELmFekxNF1CC1fqARHke/ECAwEAAaN3MHUwDwYDVR0TAQH/BAUwAwEB/zAfBgNV\nHSMEGDAWgBQFgC5rEruxtIhgyck1mfJWlgnYVzAdBgNVHQ4EFgQUBYAuaxK7sbSI\nYMnJNZnyVpYJ2FcwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEQEB/wQIMAaHBH8AAAEw\nDQYJKoZIhvcNAQELBQADggEBAHPFf7OJxMHuc7NpIR/qY9gWVyICwsDVN/V92ZDm\ng4IVhiQSyTYmtjQwbN848WRtihw3aR4FX1nvaDggHoHgdH2ug1pcdUUV4CjGTqaH\nCH5IRkg7SrlC2GimPS1LKGlB9a+nruFMevPez1Cn5OyFJ87mjcVsg+iHdhOXJD6M\ng3aN+UuslneYeLhmnupjJw4c7hZtQM8TfiuZ5ck+nGMupDXFZo5iBCS+fx9l8e3b\ntJUsmov2OmEDC+7lqkds4nBAj7GCvaD7vJr2bmwj3tNY1VURugQSIhuzWTAxohry\nM+GhLnsX+JNAU2e8E9cxCcceC8IaPAbX8y1teGCt9ukIxhE=\n-----END CERTIFICATE-----\n"
const KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAiV+E/NvfUMPee1Y8tTYdKpvTPR2SezmE1C3cQ33TvBPYf7Ce\nE+71bbWc6tA2ToNE9+z7arOm7MzNsLUAATP9gWuBy1SBzsgOUxY6GYq6xE5v9UDj\nn3qO0hCm7fmBSc6JnXpXi59QQYyfZk04HUVOWn69M6MO9wSBfIS/BOseMEAp/v+H\nwBvzJCsQxkkuM3JSsLwgG1QoavSpxhIGdtPfljrB5PSmtlSLbW2sFA21BC16Aqc3\ncCyxmeRRqvehzUw9J8Q7fzlBtOPk/RFXqVgJ003OXNmLJ/z2p0rUbCqNYgLk0wR+\nGAJYGZ3CjhIdRSg8QuYV6TE0XUILV+oBEeR78QIDAQABAoIBACYEJaD2VgwbUGAQ\ngvdhFNw8SE6S9v0b81rmoBybXzOeyFy561031Xq5dkXzPfwnTrhPwFoMgobovImI\n5YnvsdmVf1NePRgU/AXZUlXMMxhtXoVgIj35pDmU+yVDVZivzBylBUIx4ftp55jf\niMZs7hyUE1cNanBIsm7bq6M4T9/pEf41Ayf0XgkMOkjn2RpZCTdwvDASw2L0hzVv\nf9lZow1LecARdwD8dMvQ0oI7P4hSCzfTCi6JLioxLuu+8yw20Rn9/r2xV2UErPhe\nxhgxAUBLwVMlArb1c+ZVXFZpx+e1tmwmqTeAKptmFQNQkljwAEQB+6GEKhV01sQ9\nCG94SlMCgYEAwWMqdGX/KkXcCkjLbuu7qMspbI9zwoXdKc2eqp5sS6jex/gzS/Y6\nx0yMTq3wUIbHfDcVlRu9cmadW483I7DZCnRX7R0GFcW6YKA/Uog+8nykd5zA/aG8\na5tALJEd3JRNihHchxHwYpQEdklzfksN/i20CxRTehlyAQMs+jJBEz8CgYEAtdmi\ntR6YbwwxhRn7/kX/H39sEsb00sFRbSCTv8TR6nuBfmjISLY949PJ4TELj7PW7vgT\n1Rut6lsR7dSyqv6+p0J6pNfu90BUni+HRDtQyI60qiMhXqfHxpEUofkK6/er0yxN\no+Wp0NQa0788rGhNR7deTGrvQAwAl+tX2MX7FM8CgYBhrMGLqtyXMFO0ChJeAsh0\nt7BDea0BKfWLoKQsDvopuLBVFeJq0oHbmakgMDA5q+ljrrrC5hDokDWYQhyadT8a\nTar/QvKI2qaJGUcCW3hXp2a2V0EOmbr+KpreJ6mKeIk1XFIjEod0cshSKkUgG66E\nm/bcxbZn7CQtqLn14J4HpwKBgDIqQn9SXFyt8W81VtWzO4jV3ttjNSB6odrH1Npf\nEkVsIrHbd/zPAU27HALaQ8U1qEIt/1KXmyd+Tfjc5xjSw4diiHC2/L4Kag1lMRx6\nfHOHIoGYxVjWUf8OALIaAJBNt4G+xABFl8365ReqtrMc5sy04feUvEFfzj4adxZe\nrz/zAoGAU502B+/HvgdodBzdw2iQJseEG1eNaUoA1co2OxHUHlaPukt5RjOwuXrP\nobVdqbtBb9aa4ZbRl9Y1yvllJMTSzrWvWra1eV3czQOVS34FwaJ06AzaUCR7ht7D\nVOObYItn69ougXDjKwHR9t/q02fLVMmUAYBKEqaVWErMzJnssrQ=\n-----END RSA PRIVATE KEY-----\n"

const PORT = 1555

var wg sync.WaitGroup

func main() {
    startServer()

    config := &tls.Config{
        RootCAs: x509.NewCertPool(),
    }
    config.RootCAs.AppendCertsFromPEM([]byte(CRT))

    con, err := tls.Dial("tcp", "127.0.0.1:"+strconv.Itoa(1555), config)
    if err != nil {
        fmt.Println("I do not have a client cert, I should reach here")
        panic(err)
    }
    defer con.Close()

    n, err := con.Write([]byte("msg"))
    if err != nil {
        fmt.Println("At least here should be a error")
        panic(err)
    }
    fmt.Printf("Wrote %d bytes\n", n)
    wg.Wait()

}

func startServer() {
    wg.Add(1)
    cert, _ := tls.X509KeyPair([]byte(CRT), []byte(KEY))
    config := &tls.Config{
        Certificates: []tls.Certificate{cert},
        ClientAuth:   tls.RequireAndVerifyClientCert,
        ClientCAs:    x509.NewCertPool(),
    }
    config.ClientCAs.AppendCertsFromPEM([]byte(CRT))

    socket, _ := tls.Listen("tcp", ":"+strconv.Itoa(PORT), config)
    buffer := make([]byte, 1024)

    go func() {
        defer wg.Done()
        defer socket.Close()
        conn, _ := socket.Accept()

        n, _ := conn.Read(buffer)
        fmt.Println(string(buffer[:n]))
        conn.Close()

    }()
}

The Server is configured with RequireAndVerifyClientCert. If you run this example you will also see that on the server side the string msg is not printed. This I am expecting since I do not send a client certificate. But the client says the message was transmitted successful.

The strange part is, I would expect that a I got an error during the tls.Dial call on the client side. But maybe this is just the tcp connection and tls will be done later. But the really strange part is, that i can call the write function and this does not return an error and even returns n=3 indecating that the server received 3 bytes.

Note: If you change RequireAndVerifyClientCert to NoClientCert the server part will correctly receive the message.

Why does go not tell me that the tls handshake has failed? Or does it really not fail (What am I doing wrong)?

user3046582
  • 341
  • 3
  • 15
  • 1
    There is no error checking on the server-side (unless this was left out for brevity). FYI... you will not see an error on Dial - this only opens a connection, it does not send any bytes - and thus the `TLS` layer has not kicked in yet. – colm.anseo Mar 13 '23 at 15:59
  • Yes, I ignore all errors on the server side for this example for simplicity. I also notice the Handschake function on the client sind that should trigger tls handschake ? But also this gives me not an error… – user3046582 Mar 13 '23 at 16:42

1 Answers1

0

I tried a lot more. I think it is either a bug or some sort of intentional.

I ask the question in the go project. -> https://github.com/golang/go/issues/59012

user3046582
  • 341
  • 3
  • 15