th5/_dev/tris-testclient/client.go
Peter Wu c89a0a5f3a tris: Add initial client interoperability tests
Prepare framework for testing tls-tris as client against other servers.
Currently only boringssl is implemented, but the idea is to add support
for others too (NSS, OpenSSL, picotls, tris, ...).

To test multiple certificate types, copy ecdsa.pem and rsa.pem from
tris-localserver for boringssl. The boringssl image is reused for the
server since the binaries were built anyway. Revision is bumped to
something to fix a build error and make the -loop and -www options work.
2017-12-13 17:39:53 +00:00

122 lines
3.2 KiB
Go

package main
import (
"crypto/tls"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
)
var tlsVersionToName = map[uint16]string{
tls.VersionTLS10: "1.0",
tls.VersionTLS11: "1.1",
tls.VersionTLS12: "1.2",
tls.VersionTLS13: "1.3",
tls.VersionTLS13Draft18: "1.3 (draft 18)",
}
var cipherSuiteIdToName = map[uint16]string{
tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
}
type Client struct {
KeyLogWriter io.Writer
failed uint
}
func (c *Client) run(addr string, version, cipherSuite uint16) {
fmt.Printf("TLS %s with %s\n", tlsVersionToName[version], cipherSuiteIdToName[cipherSuite])
tls_config := &tls.Config{
InsecureSkipVerify: true,
MinVersion: version,
MaxVersion: version,
CipherSuites: []uint16{cipherSuite},
KeyLogWriter: c.KeyLogWriter,
}
con, err := tls.Dial("tcp", addr, tls_config)
if err != nil {
fmt.Printf("handshake failed: %v\n\n", err)
c.failed++
return
}
defer con.Close()
_, err = con.Write([]byte("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"))
if err != nil {
fmt.Printf("Write failed: %v\n\n", err)
c.failed++
return
}
buf := make([]byte, 1024)
n, err := con.Read(buf)
if err != nil {
fmt.Printf("Read failed: %v\n\n", err)
c.failed++
return
}
fmt.Printf("Read %d bytes\n", n)
fmt.Println("OK\n")
}
func main() {
var keylog_file string
var enable_rsa, enable_ecdsa bool
flag.StringVar(&keylog_file, "keylogfile", "", "Secrets will be logged here")
flag.BoolVar(&enable_rsa, "rsa", true, "Whether to enable RSA cipher suites")
flag.BoolVar(&enable_ecdsa, "ecdsa", true, "Whether to enable ECDSA cipher suites")
flag.Parse()
if flag.NArg() != 1 {
flag.Usage()
os.Exit(1)
}
addr := flag.Arg(0)
if !strings.Contains(addr, ":") {
addr += ":443"
}
client := Client{}
if keylog_file == "" {
keylog_file = os.Getenv("SSLKEYLOGFILE")
}
if keylog_file != "" {
keylog_writer, err := os.OpenFile(keylog_file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Cannot open keylog file: %v", err)
}
client.KeyLogWriter = keylog_writer
log.Println("Enabled keylog")
}
if enable_rsa {
// Sanity check: TLS 1.2 with the mandatory cipher suite from RFC 5246
client.run(addr, tls.VersionTLS12, tls.TLS_RSA_WITH_AES_128_CBC_SHA)
}
if enable_ecdsa {
// Sane cipher suite for TLS 1.2 with an ECDSA cert (as used by boringssl)
client.run(addr, tls.VersionTLS12, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
}
client.run(addr, tls.VersionTLS13, tls.TLS_CHACHA20_POLY1305_SHA256)
client.run(addr, tls.VersionTLS13, tls.TLS_AES_128_GCM_SHA256)
client.run(addr, tls.VersionTLS13, tls.TLS_AES_256_GCM_SHA384)
// TODO test with client cert
// TODO test other kex methods besides X25519, like MTI secp256r1
// TODO limit supported groups?
if client.failed > 0 {
log.Fatalf("Failed handshakes: %d\n", client.failed)
} else {
fmt.Println("All handshakes passed")
}
}