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.
This commit is contained in:
Peter Wu 2017-08-31 15:03:22 +01:00
parent dee13626ef
commit c89a0a5f3a
10 changed files with 242 additions and 6 deletions

View File

@ -8,7 +8,7 @@ go:
- 1.7
env:
- MODE=interop CLIENT=boring
- MODE=interop CLIENT=boring SERVER=boring
- MODE=interop CLIENT=tstclnt
- MODE=interop CLIENT=picotls ZRTT=1
- MODE=interop CLIENT=mint
@ -28,10 +28,13 @@ matrix:
install:
- if [ "$MODE" = "interop" ]; then ./_dev/tris-localserver/start.sh -d && docker ps -a; fi
- if [ "$MODE" = "interop" ]; then ./_dev/interop.sh INSTALL $CLIENT $REVISION; fi
- if [ -n "$SERVER" -a "$CLIENT" != "$SERVER" ]; then ./_dev/interop.sh INSTALL $SERVER $REVISION; fi
- if [ -n "$SERVER" ]; then ./_dev/interop.sh INSTALL-CLIENT; fi
script:
- if [ "$MODE" = "interop" ]; then ./_dev/interop.sh RUN $CLIENT; fi
- if [ "$MODE" = "interop" ] && [ "$ZRTT" = "1" ]; then ./_dev/interop.sh 0-RTT $CLIENT; fi
- if [ -n "$SERVER" ]; then ./_dev/interop.sh RUN-CLIENT $SERVER; fi
- if [ "$MODE" = "gotest" ]; then ./_dev/go.sh test -race crypto/tls; fi
- if [ "$MODE" = "bogo" ]; then ./_dev/bogo.sh; fi

1
_dev/.gitignore vendored
View File

@ -1,5 +1,6 @@
/GOROOT
/go
/tris-localserver/tris-localserver
/tris-testclient/tris-testclient
/caddy/caddy
/caddy/echo

View File

@ -12,11 +12,7 @@ RUN apk add --update \
RUN git clone https://boringssl.googlesource.com/boringssl
# Cacheable layer of compilation, to make the next incremental
RUN cd boringssl && git checkout 9b885c5
RUN mkdir boringssl/build
RUN cd boringssl/build && cmake -GNinja ..
RUN cd boringssl && ninja -C build
# Draft 14
# ARG REVISION=88536c3
@ -38,7 +34,9 @@ RUN cd boringssl && ninja -C build
# ARG REVISION=89917a5
# Draft 18
ARG REVISION=9b885c5
#ARG REVISION=9b885c5
# Draft 18, but with "bssl server -loop -www" support and build fix
ARG REVISION=40b24c8154
RUN cd boringssl && git fetch
RUN cd boringssl && git checkout $REVISION
@ -47,4 +45,5 @@ RUN cd boringssl && ninja -C build
ADD httpreq.txt /httpreq.txt
ADD run.sh /run.sh
ADD server.sh rsa.pem ecdsa.pem /
ENTRYPOINT ["/run.sh"]

15
_dev/boring/ecdsa.pem Normal file
View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIIBbTCCAROgAwIBAgIQZCsHZcs5ZkzV+zC2E6j5RzAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE2MDkyNDE3NTE1OFoXDTI2MDkyMjE3NTE1OFow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDTO
B3IyzjYfKCp2HWy+P3QHxhdBT4AUGYgwTiSEj5phumPIahFNcOSWptN0UzlZvJdN
MMjVmrFYK/FjF4abkNKjSzBJMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggq
hkjOPQQDAgNIADBFAiEAp9W157PM1IadPBc33Cbj7vaFvp+rXs/hSuMCzP8pgV8C
IHCswo1qiC0ZjQmWsBlmz5Zbp9rOorIzBYmGRhRdNs3j
-----END CERTIFICATE-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFdhO7IW5UIwpB1e2Vunm9QyKvUHWcVwGfLjhpOajuR7oAoGCCqGSM49
AwEHoUQDQgAENM4HcjLONh8oKnYdbL4/dAfGF0FPgBQZiDBOJISPmmG6Y8hqEU1w
5Jam03RTOVm8l00wyNWasVgr8WMXhpuQ0g==
-----END EC PRIVATE KEY-----

45
_dev/boring/rsa.pem Normal file
View File

@ -0,0 +1,45 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1DHcIM3SThFqy8nAkPQFX0E7ph8jqh8EATXryjKHGuVjR3Xh
OQ0BSPoJxyfdg/VEwevFrtmZAfz0WCbxvP2SVCmf7oobg4V2KPSo3nNt9vlBFUne
RtIyHRQ8YRnGSWaRHzJbX6ffltnG2aD+8qUfk161rdZgxBA9G0Ga47IkwQhT2Hqu
H3dW2Uu4W2WMyt6gX/tdyEAV57MOPcoceknr7Nb2kfiuDPR7h6wFrW3I6eoj8oX2
SkIOuVNt1Z31BAUcPJDUjqopI0o9tolM/7X13M8dEY0OJQVr7FQYDF9JeSYeEMyb
wizjBaHDm48mSghP1o5UssQBbNNC83btXCjiLQIDAQABAoIBACzvGgRAUYaCnbDl
2kdXxUN0luMIuQ6vXrO67WF17bI+XRWm2riwDlObzzJDON9Wsua1vLjYD1SickOw
i4RP1grIfbuPt1/UhT8LAC+LFgA0rBmL+OvaWw5ZWKffQ2QLujN3AG5zKB/Tog43
z4UmfldAuQxE11zta2M4M0qAUNQnQj1oiuI8RUdG0VvvLw8Htdi1ogH0CI5R669z
NjHt+JV+2gzKx6EX0s8mQL3yXGkC2xXItRbFclyCMJEhPS7QbBu+tru35N6WpzAq
BCl2Q7LQogvSA6MXuMOx6CyuExVfgmhbfeoheLE8gmXwl0Y37n/g6ZBZFAtpCjcs
UckPv0ECgYEA1orl7RwgIsZljMap6vWtMGoRIHKmT91DGpMmkh4suZe+yAk85maU
49Vd+8ZfIN41AH37yrsGOcPHgz5o5QufELpoub6DCsQ7u9F1vQp55cp+qyBWzAgz
b/xUuVnIyv3kLan3fpk7ZGCBXFBpLG0QXMFOHtda3Mlk5SmuoEYaYRkCgYEA/TLR
u4neKqyqwsqMuRJGC1iKFVmfCjZeNMtPNbTWpdqez/vvT8APnEpIumUGt8YROLGZ
8biUr5/ViOkmaP3wmQbO9m2/cE01lMTYv75w1cw2KVQe6kAHJkOx+JEx9xg53RJ/
QlFtG5MQUy2599Gxp8BMGaXLH5yo4qwvNvY6CDUCgYEArxr7AwX7rKZlZ/sV4HHY
gzVu+R7aY0DibiRATO5X7rrNuhLgI+UCDNqvNLn6FqeGdvpcsmDneeozQwmDL77G
ey7KHyBBcF4tquQQxtRwHX+i1yUz8p+W7AX1WLrRSezjeenJ2QhUE1849hGjZeE2
g546lq2Kub2enfPhVWsiSLECgYEA72T5QCPeVuLioUH5Q5Kvf1K7W+xcnr9A2xHP
Vqwgtre5qFQ/tFuXZuIlWXbjnyY6aiwhrZYjntm0f7pRgrt2nHj/fafOdVPK8Voc
xU4+SSbHntPWVw0qtVcUEjzVzRauvwMaJ43tZ0DpEnwNdO5i1oTObwF+x+jLFWZP
TdwIinECgYBzjZeCxxOMk5SlPpTsLUtgC+q3m1AavXhUVNEPP2gKMOIPTETPbhbG
LBxB2vVbJiS3J7itQy8gceT89O0vSEZnaTPXiM/Ws1QbkBJ8yW7KI7X4WuzN4Imq
/cLBRXLb8R328U27YyQFNGMjr2tX/+vx5FulJjSloWMRNuFWUngv7w==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC+jCCAeKgAwIBAgIRANBDimJ/ww2tz77qcYIhuZowDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA5MjQxNzI5MTlaFw0yNjA5MjIxNzI5
MTlaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDUMdwgzdJOEWrLycCQ9AVfQTumHyOqHwQBNevKMoca5WNHdeE5DQFI
+gnHJ92D9UTB68Wu2ZkB/PRYJvG8/ZJUKZ/uihuDhXYo9Kjec232+UEVSd5G0jId
FDxhGcZJZpEfMltfp9+W2cbZoP7ypR+TXrWt1mDEED0bQZrjsiTBCFPYeq4fd1bZ
S7hbZYzK3qBf+13IQBXnsw49yhx6Sevs1vaR+K4M9HuHrAWtbcjp6iPyhfZKQg65
U23VnfUEBRw8kNSOqikjSj22iUz/tfXczx0RjQ4lBWvsVBgMX0l5Jh4QzJvCLOMF
ocObjyZKCE/WjlSyxAFs00Lzdu1cKOItAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAygPV4enmvwSuMd1JarxOXpOK
Z4Nsk7EKlfCPgzxQUOkFdLIr5ZG1kUkQt/omzTmoIWjLAsoYzT0ZCPOrioczKsWj
MceFUIkT0w+eIl+8DzauPy34o8rjcApglF165UG3iphlpI+jdPzv5TBarUAbwsFb
ClMLEiNJQ0OMxAIaRtb2RehD4q3OWlpWf6joJ36PRBqL8T5+f2x6Tg3c64UR+QPX
98UcCQHHdEhm7y2z5Z2Wt0B48tZ+UAxDEoEwMghNyw7wUD79IRlXGYypBnXaMuLX
46aGxbsSQ7Rfg62Co3JG7vo+eJd0AoZHrtFUnfM8V70IFzMBZnSwRslHRJe56Q==
-----END CERTIFICATE-----

17
_dev/boring/server.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
PATH=/boringssl/build/tool:$PATH
set -x
# RSA
bssl server \
-key rsa.pem \
-min-version tls1.2 -max-version tls1.3 \
-accept 1443 -loop -www 2>&1 &
# ECDSA
bssl server \
-key ecdsa.pem \
-min-version tls1.2 -max-version tls1.3 \
-accept 2443 -loop -www 2>&1 &
wait

View File

@ -2,6 +2,7 @@
set -xeuo pipefail
if [ "$1" = "INSTALL" ]; then
# INSTALL <client> [<revision>]
if [ -n "${3:-}" ]; then
REVISION="--build-arg REVISION=$3"
else
@ -10,6 +11,7 @@ if [ "$1" = "INSTALL" ]; then
docker build $REVISION -t tls-tris:$2 _dev/$2
elif [ "$1" = "RUN" ]; then
# RUN <client>
IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver)
docker run --rm tls-tris:$2 $IP:1443 | tee output.txt # RSA
@ -21,6 +23,7 @@ elif [ "$1" = "RUN" ]; then
grep "Hello TLS 1.3" output.txt | grep "resumed" | grep -v "0-RTT"
elif [ "$1" = "0-RTT" ]; then
# 0-RTT <client>
IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver)
docker run --rm tls-tris:$2 $IP:3443 | tee output.txt # rejecting 0-RTT
@ -32,4 +35,24 @@ elif [ "$1" = "0-RTT" ]; then
docker run --rm tls-tris:$2 $IP:5443 | tee output.txt # confirming 0-RTT
grep "Hello TLS 1.3" output.txt | grep "resumed" | grep "0-RTT confirmed"
elif [ "$1" = "INSTALL-CLIENT" ]; then
cd "$(dirname "$0")/tris-testclient"
./build.sh
elif [ "$1" = "RUN-CLIENT" ]; then
# RUN-CLIENT <target-server>
cd "$(dirname "$0")/tris-testclient"
servername="$2-localserver"
docker run --rm --detach --name "$servername" \
--entrypoint /server.sh \
--expose 1443 --expose 2443 \
tls-tris:$2
IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' "$servername")
# Obtain information and stop server on exit
trap 'docker ps -a; docker logs "$servername"; docker kill "$servername"' EXIT
docker run --rm tris-testclient -ecdsa=false $IP:1443 # RSA
docker run --rm tris-testclient -rsa=false $IP:2443 # ECDSA
# TODO maybe check server logs for expected output?
fi

View File

@ -0,0 +1,7 @@
FROM scratch
ENV TLSDEBUG error
ADD tris-testclient /
ENTRYPOINT ["/tris-testclient"]

5
_dev/tris-testclient/build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
set -e
cd "$(dirname "$0")"
GOOS=linux ../go.sh build -v -i .
docker build -t tris-testclient .

View File

@ -0,0 +1,121 @@
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")
}
}