diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..eac8dfa --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +sudo: required +language: go + +services: + - docker + +go: + - 1.7 + +env: + - MODE=gotest + - MODE=interop CLIENT=boring + - MODE=interop CLIENT=boring REVISION=origin/master + - MODE=interop CLIENT=bogo + - MODE=interop CLIENT=bogo REVISION=origin/master + - MODE=interop CLIENT=tstclnt + - MODE=interop CLIENT=tstclnt REVISION=default + - MODE=interop CLIENT=mint + +matrix: + fast_finish: true + allow_failures: + - env: MODE=interop CLIENT=bogo REVISION=origin/master + - env: MODE=interop CLIENT=boring REVISION=origin/master + - env: MODE=interop CLIENT=tstclnt REVISION=default + +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 + +script: + - if [ "$MODE" = "interop" ]; then ./_dev/interop.sh RUN $CLIENT 443; fi # ECDSA + - if [ "$MODE" = "interop" ]; then ./_dev/interop.sh RUN $CLIENT 4443; fi # RSA + - if [ "$MODE" = "gotest" ]; then ./_dev/go.sh test crypto/tls; fi + +after_script: + - if [ "$MODE" = "interop" ]; then docker ps -a; docker logs tris-localserver; fi + +cache: + directories: + - _dev/GOROOT + - _dev/go diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a260bb --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +``` + _____ _ ____ _ _ +|_ _| | / ___| | |_ _ __(_)___ + | | | | \___ \ _____| __| '__| / __| + | | | |___ ___) |_____| |_| | | \__ \ + |_| |_____|____/ \__|_| |_|___/ + +``` + +crypto/tls, now with 100% more 1.3. + +DO NOT USE THIS FOR THE SAKE OF EVERYTHING THAT'S GOOD AND JUST. + +[![Build Status](https://travis-ci.org/cloudflare/tls-tris.svg?branch=master)](https://travis-ci.org/cloudflare/tls-tris) + +## Usage + +Since `crypto/tls` is very deeply (and not that elegantly) coupled with the Go stdlib, +tls-tris shouldn't be used as an external package. It is also impossible to vendor it +as `crypto/tls` because stdlib packages would import the standard one and mismatch. + +So, to build with tls-tris, you need to use a custom GOROOT. +A script is provided that will take care of it for you: `./_dev/go.sh`. +Just use that instead of the `go` tool. + +The script also transparently fetches the custom Cloudflare Go compiler with the required backports. + +``` +./_dev/go.sh build ./_dev/tris-localserver +TLSDEBUG=error ./tris-localserver 127.0.0.1:4443 +``` + +## Debugging + +When the environment variable `TLSDEBUG` is set to `error`, Tris will print a hexdump of the Client Hello and a stack trace if an handshake error occurs. + +## Building Caddy + +``` +./_dev/go.sh build github.com/mholt/caddy +``` + +*Note: to get Caddy to use TLS 1.3 you'll have to apply the patch at `_dev/caddy/caddy.patch`.* + +## Testing with Firefox + +1. Download the latest Firefox Nightly +1. Navigate to about:config and set `security.tls.version.max` to `4` +1. Connect to https://tris.filippo.io/ or tris-localserver + +## Testing with BoringSSL/BoGo/NSS/Mint + +``` +./_dev/tris-localserver/start.sh --rm +``` + +``` +docker build -t tls-tris:boring _dev/boring +docker run -i --rm tls-tris:boring $(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver):443 +``` + +``` +docker build -t tls-tris:bogo _dev/bogo +docker run -i --rm tls-tris:bogo $(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver):443 +``` + +``` +docker build -t tls-tris:tstclnt _dev/tstclnt +docker run -i --rm tls-tris:tstclnt $(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver):443 +``` + +``` +docker build -t tls-tris:mint _dev/mint +docker run -i --rm tls-tris:mint $(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver):443 +``` + +To build a specific revision, use `--build-arg REVISION=abcdef1234`. diff --git a/_dev/.gitignore b/_dev/.gitignore new file mode 100644 index 0000000..7bd4d28 --- /dev/null +++ b/_dev/.gitignore @@ -0,0 +1,4 @@ +/GOROOT +/go +/tris-localserver/tris-localserver +/caddy/caddy diff --git a/_dev/Makefile b/_dev/Makefile new file mode 100644 index 0000000..c699600 --- /dev/null +++ b/_dev/Makefile @@ -0,0 +1,38 @@ +GO ?= go +GOENV := $(shell $(GO) env GOOS)_$(shell $(GO) env GOARCH) +GOROOTINFO := $(shell $(GO) version | cut -d' ' -f 3)_$(GOENV) + +.PHONY: GOROOT +GOROOT: GOROOT/$(GOENV)/.ok_$(GOROOTINFO) + @rm -f GOROOT/$(GOENV)/pkg/*/crypto/tls.a + +GOROOT/$(GOENV)/.ok_$(GOROOTINFO): + rm -rf GOROOT/$(GOENV) + mkdir -p GOROOT/$(GOENV)/pkg + cp -r "$(shell $(GO) env GOROOT)/src" GOROOT/$(GOENV)/src + cp -r "$(shell $(GO) env GOROOT)/pkg/include" GOROOT/$(GOENV)/pkg/include + cp -r "$(shell $(GO) env GOROOT)/pkg/tool" GOROOT/$(GOENV)/pkg/tool + rm -r GOROOT/$(GOENV)/src/crypto/tls + ln -s ../../../../.. GOROOT/$(GOENV)/src/crypto/tls + GOROOT="$(CURDIR)/GOROOT/$(GOENV)" $(GO) install -v std +ifeq ($(shell go env CGO_ENABLED),1) + GOROOT="$(CURDIR)/GOROOT/$(GOENV)" $(GO) install -race -v std +endif + @touch "$@" + +GO_COMMIT := 5782050a487e002acfd14a3f4c2c815c7854928c + +.PHONY: go +go: go/.ok_$(GO_COMMIT)_$(GOENV) + +go/.ok_$(GO_COMMIT)_$(GOENV): + rm -rf go/.ok_*_$(GOENV) go/$(GOENV) + mkdir -p go + git clone --branch 1.7.3 --single-branch --depth 25 https://github.com/cloudflare/go go/$(GOENV) + cd go/$(GOENV) && git checkout $(GO_COMMIT) + cd go/$(GOENV)/src && GOROOT_BOOTSTRAP="$(shell $(GO) env GOROOT)" ./make.bash + @touch "$@" + +.PHONY: clean +clean: + rm -rf GOROOT go diff --git a/_dev/bogo/Dockerfile b/_dev/bogo/Dockerfile new file mode 100644 index 0000000..c75245f --- /dev/null +++ b/_dev/bogo/Dockerfile @@ -0,0 +1,25 @@ +FROM alpine + +RUN apk add --update \ + git \ + cmake \ + perl \ + python \ + build-base \ + go \ + ninja \ + && rm -rf /var/cache/apk/* + +RUN git clone https://boringssl.googlesource.com/boringssl + +# see _dev/boring for REVISION info +ARG REVISION=9b885c5 + +RUN cd boringssl && git fetch +RUN cd boringssl && git checkout $REVISION + +ADD bogo-client.go /bogo-client.go +RUN go build /bogo-client.go + +ADD run.sh /run.sh +ENTRYPOINT ["/run.sh"] diff --git a/_dev/bogo/bogo-client.go b/_dev/bogo/bogo-client.go new file mode 100644 index 0000000..6707303 --- /dev/null +++ b/_dev/bogo/bogo-client.go @@ -0,0 +1,28 @@ +package main + +import ( + "log" + "net" + "net/http" + "os" + + "./boringssl/ssl/test/runner" +) + +func main() { + tr := &http.Transport{ + DialTLS: func(network, addr string) (net.Conn, error) { + return runner.Dial(network, addr, &runner.Config{ + InsecureSkipVerify: true, + }) + }, + } + client := &http.Client{Transport: tr} + resp, err := client.Get("https://" + os.Args[1]) + if err != nil { + log.Fatal(err) + } + if err := resp.Write(os.Stdout); err != nil { + log.Fatal(err) + } +} diff --git a/_dev/bogo/run.sh b/_dev/bogo/run.sh new file mode 100755 index 0000000..9f849a8 --- /dev/null +++ b/_dev/bogo/run.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +exec /bogo-client "$@" diff --git a/_dev/boring/Dockerfile b/_dev/boring/Dockerfile new file mode 100644 index 0000000..2f08a37 --- /dev/null +++ b/_dev/boring/Dockerfile @@ -0,0 +1,47 @@ +FROM alpine + +RUN apk add --update \ + git \ + cmake \ + perl \ + python \ + build-base \ + go \ + ninja \ + && rm -rf /var/cache/apk/* + +RUN git clone https://boringssl.googlesource.com/boringssl +RUN mkdir boringssl/build +RUN cd boringssl/build && cmake -GNinja .. +RUN cd boringssl && ninja -C build + +# Draft 14 +# ARG REVISION=88536c3 + +# Draft 15 +# RUN cd boringssl && git fetch https://boringssl.googlesource.com/boringssl refs/changes/40/10840/18:draft15 +# ARG REVISION=cae930d + +# Draft "14.25" (sigalg renumbering) +# ARG REVISION=af56fbd + +# Draft "14.25" w/ x25519 only +# ARG REVISION=c8b6b4f + +# Draft "14.5" (sigalg, x25519, version ext) +# ARG REVISION=54afdab + +# Draft 16 +# ARG REVISION=89917a5 + +# Draft 18 +ARG REVISION=9b885c5 + +RUN cd boringssl && git fetch +RUN cd boringssl && git checkout $REVISION +RUN cd boringssl/build && cmake -GNinja .. +RUN cd boringssl && ninja -C build + +ADD httpreq.txt /httpreq.txt +ADD run.sh /run.sh +ENTRYPOINT ["/run.sh"] diff --git a/_dev/boring/httpreq.txt b/_dev/boring/httpreq.txt new file mode 100644 index 0000000..e4e6ac1 --- /dev/null +++ b/_dev/boring/httpreq.txt @@ -0,0 +1,5 @@ +GET / HTTP/1.1 +Host: example.com +Connection: close + + diff --git a/_dev/boring/run.sh b/_dev/boring/run.sh new file mode 100755 index 0000000..7da9c43 --- /dev/null +++ b/_dev/boring/run.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +exec /boringssl/build/tool/bssl s_client -min-version tls1.3 -max-version tls1.3 -connect "$@" < /httpreq.txt diff --git a/_dev/caddy/Caddyfile b/_dev/caddy/Caddyfile new file mode 100644 index 0000000..10c462c --- /dev/null +++ b/_dev/caddy/Caddyfile @@ -0,0 +1,12 @@ +tris.filippo.io { + tls bip@filippo.io + gzip + log stdout + proxy / https://blog.filippo.io +} + +cf.tris.filippo.io { + tls bip@filippo.io + log stdout + proxy / https://blog.cloudflare.com +} diff --git a/_dev/caddy/Dockerfile b/_dev/caddy/Dockerfile new file mode 100644 index 0000000..9f870fd --- /dev/null +++ b/_dev/caddy/Dockerfile @@ -0,0 +1,18 @@ +FROM scratch + +# docker create -v /root/.caddy --name caddy-data caddy /bin/true +# docker run -d --restart always --volumes-from caddy-data -p 80:80 -p 443:443 caddy + +# go get -d -v github.com/mholt/caddy/caddy +# GOOS=linux ../go.sh build -v -i github.com/mholt/caddy/caddy +ADD caddy caddy +ADD Caddyfile Caddyfile +ADD https://mkcert.org/generate/ /etc/ssl/certs/ca-certificates.crt + +EXPOSE 80 +EXPOSE 443 + +ENV TLSDEBUG error +ENV HOME /root/ + +CMD [ "/caddy" ] diff --git a/_dev/caddy/caddy.patch b/_dev/caddy/caddy.patch new file mode 100644 index 0000000..3332c2c --- /dev/null +++ b/_dev/caddy/caddy.patch @@ -0,0 +1,56 @@ +diff --git a/caddytls/config.go b/caddytls/config.go +index 91c7451..c3e87d5 100644 +--- a/caddytls/config.go ++++ b/caddytls/config.go +@@ -241,6 +241,7 @@ func MakeTLSConfig(configs []*Config) (*tls.Config, error) { + if i > 0 && cfg.PreferServerCipherSuites != configs[i-1].PreferServerCipherSuites { + return nil, fmt.Errorf("cannot both use PreferServerCipherSuites and not use it") + } ++ config.PreferServerCipherSuites = cfg.PreferServerCipherSuites + + // Go with the widest range of protocol versions + if cfg.ProtocolMinVersion < config.MinVersion { +@@ -335,7 +336,7 @@ func SetDefaultTLSParams(config *Config) { + config.ProtocolMinVersion = tls.VersionTLS11 + } + if config.ProtocolMaxVersion == 0 { +- config.ProtocolMaxVersion = tls.VersionTLS12 ++ config.ProtocolMaxVersion = tls.VersionTLS13 + } + + // Prefer server cipher suites +@@ -357,6 +358,7 @@ var supportedProtocols = map[string]uint16{ + "tls1.0": tls.VersionTLS10, + "tls1.1": tls.VersionTLS11, + "tls1.2": tls.VersionTLS12, ++ "tls1.3": tls.VersionTLS13, + } + + // Map of supported ciphers, used only for parsing config. +@@ -370,6 +372,8 @@ var supportedProtocols = map[string]uint16{ + // + // This map, like any map, is NOT ORDERED. Do not range over this map. + var supportedCiphersMap = map[string]uint16{ ++ "ECDHE-ECDSA-CHACHA20-POLY1305": tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, ++ "ECDHE-RSA-CHACHA20-POLY1305": tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + "ECDHE-RSA-AES256-GCM-SHA384": tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + "ECDHE-ECDSA-AES256-GCM-SHA384": tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + "ECDHE-RSA-AES128-GCM-SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +@@ -391,6 +395,8 @@ var supportedCiphersMap = map[string]uint16{ + // Note that TLS_FALLBACK_SCSV is not in this list since it is always + // added manually. + var supportedCiphers = []uint16{ ++ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, ++ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, +@@ -407,6 +413,8 @@ var supportedCiphers = []uint16{ + + // List of all the ciphers we want to use by default + var defaultCiphers = []uint16{ ++ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, ++ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, diff --git a/_dev/go.sh b/_dev/go.sh new file mode 100755 index 0000000..fa7babf --- /dev/null +++ b/_dev/go.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +BASEDIR=$(cd "$(dirname "$0")" && pwd) + +make --quiet -C "$BASEDIR" go >&2 +GOENV="$(go env GOOS)_$(go env GOARCH)" + +unset GOROOT +make --quiet -C "$BASEDIR" GOROOT GO="$BASEDIR/go/$GOENV/bin/go" >&2 +export GOROOT="$BASEDIR/GOROOT/$GOENV" + +exec $BASEDIR/go/$GOENV/bin/go "$@" diff --git a/_dev/interop.sh b/_dev/interop.sh new file mode 100755 index 0000000..4f9ac30 --- /dev/null +++ b/_dev/interop.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -xeuo pipefail + +if [ "$1" = "INSTALL" ]; then + if [ -n "${3:-}" ]; then + REVISION="--build-arg REVISION=$3" + else + REVISION="" + fi + docker build $REVISION -t tls-tris:$2 _dev/$2 + +elif [ "$1" = "RUN" ]; then + IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' tris-localserver) + docker run -i --rm tls-tris:$2 $IP:$3 | tee output.txt + grep "Hello TLS 1.3" output.txt + +fi diff --git a/_dev/mint/Dockerfile b/_dev/mint/Dockerfile new file mode 100644 index 0000000..5e769f2 --- /dev/null +++ b/_dev/mint/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.7-alpine + +RUN apk add --update \ + git \ + && rm -rf /var/cache/apk/* + +RUN go get github.com/bifurcation/mint + +# Draft 18 +ARG REVISION=271abd1 + +RUN cd /go/src/github.com/bifurcation/mint && git fetch +RUN cd /go/src/github.com/bifurcation/mint && git checkout $REVISION + +ADD mint-client.go /mint-client.go +RUN GOBIN=/ go install /mint-client.go + +ENV MINT_LOG=* + +ADD run.sh /run.sh +ENTRYPOINT ["/run.sh"] diff --git a/_dev/mint/mint-client.go b/_dev/mint/mint-client.go new file mode 100644 index 0000000..d344e3e --- /dev/null +++ b/_dev/mint/mint-client.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + "net" + "net/http" + "os" + + "github.com/bifurcation/mint" +) + +func main() { + tr := &http.Transport{ + DialTLS: func(network, addr string) (net.Conn, error) { + return mint.Dial(network, addr, nil) + }, + } + client := &http.Client{Transport: tr} + resp, err := client.Get("https://" + os.Args[1]) + if err != nil { + log.Fatal(err) + } + if err := resp.Write(os.Stdout); err != nil { + log.Fatal(err) + } +} diff --git a/_dev/mint/run.sh b/_dev/mint/run.sh new file mode 100755 index 0000000..013915a --- /dev/null +++ b/_dev/mint/run.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +exec /mint-client "$@" diff --git a/_dev/tris-localserver/Dockerfile b/_dev/tris-localserver/Dockerfile new file mode 100644 index 0000000..fd5ef67 --- /dev/null +++ b/_dev/tris-localserver/Dockerfile @@ -0,0 +1,10 @@ +FROM scratch + +# GOOS=linux ../go.sh build -v -i . +ADD tris-localserver ./ + +ENV TLSDEBUG error + +EXPOSE 443 +EXPOSE 4443 +CMD [ "./tris-localserver", "0.0.0.0:443", "0.0.0.0:4443" ] diff --git a/_dev/tris-localserver/server.go b/_dev/tris-localserver/server.go new file mode 100644 index 0000000..afc0872 --- /dev/null +++ b/_dev/tris-localserver/server.go @@ -0,0 +1,124 @@ +package main + +import ( + "crypto/tls" + "encoding/hex" + "fmt" + "log" + "net/http" + "os" +) + +var tlsVersionToName = map[uint16]string{ + tls.VersionTLS10: "1.0", + tls.VersionTLS11: "1.1", + tls.VersionTLS12: "1.2", + tls.VersionTLS13: "1.3", + 0x7f00 | 16: "1.3 (draft 16)", + 0x7f00 | 18: "1.3 (draft 18)", +} + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "

Hello TLS %s _o/\n", tlsVersionToName[r.TLS.Version]) + }) + + http.HandleFunc("/ch", func(w http.ResponseWriter, r *http.Request) { + r.Header.Set("Content-Type", "text/plain") + fmt.Fprintf(w, "Client Hello packet (%d bytes):\n%s", len(r.TLS.ClientHello), hex.Dump(r.TLS.ClientHello)) + }) + + go func() { + if len(os.Args) < 3 { + return + } + cert, err := tls.X509KeyPair([]byte(rsaCert), []byte(rsaKey)) + if err != nil { + log.Fatal(err) + } + s := &http.Server{ + Addr: os.Args[2], + TLSConfig: &tls.Config{ + Certificates: []tls.Certificate{cert}, + PreferServerCipherSuites: true, + }, + } + log.Fatal(s.ListenAndServeTLS("", "")) + }() + + cert, err := tls.X509KeyPair([]byte(ecdsaCert), []byte(ecdsaKey)) + if err != nil { + log.Fatal(err) + } + s := &http.Server{ + Addr: os.Args[1], + TLSConfig: &tls.Config{ + Certificates: []tls.Certificate{cert}, + PreferServerCipherSuites: true, + }, + } + log.Fatal(s.ListenAndServeTLS("", "")) +} + +const ( + rsaKey = `-----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-----` + rsaCert = `-----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-----` + ecdsaCert = `-----BEGIN CERTIFICATE----- +MIIBbTCCAROgAwIBAgIQZCsHZcs5ZkzV+zC2E6j5RzAKBggqhkjOPQQDAjASMRAw +DgYDVQQKEwdBY21lIENvMB4XDTE2MDkyNDE3NTE1OFoXDTI2MDkyMjE3NTE1OFow +EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDTO +B3IyzjYfKCp2HWy+P3QHxhdBT4AUGYgwTiSEj5phumPIahFNcOSWptN0UzlZvJdN +MMjVmrFYK/FjF4abkNKjSzBJMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggq +hkjOPQQDAgNIADBFAiEAp9W157PM1IadPBc33Cbj7vaFvp+rXs/hSuMCzP8pgV8C +IHCswo1qiC0ZjQmWsBlmz5Zbp9rOorIzBYmGRhRdNs3j +-----END CERTIFICATE-----` + ecdsaKey = `-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFdhO7IW5UIwpB1e2Vunm9QyKvUHWcVwGfLjhpOajuR7oAoGCCqGSM49 +AwEHoUQDQgAENM4HcjLONh8oKnYdbL4/dAfGF0FPgBQZiDBOJISPmmG6Y8hqEU1w +5Jam03RTOVm8l00wyNWasVgr8WMXhpuQ0g== +-----END EC PRIVATE KEY-----` +) diff --git a/_dev/tris-localserver/start.sh b/_dev/tris-localserver/start.sh new file mode 100755 index 0000000..edd54f3 --- /dev/null +++ b/_dev/tris-localserver/start.sh @@ -0,0 +1,9 @@ +#! /bin/sh +set -e + +cd "$(dirname $0)" + +CGO_ENABLED=0 GOOS=linux ../go.sh build -v -i . +docker build -t tris-localserver . +exec docker run --name tris-localserver --env TLSDEBUG=error "$@" tris-localserver + diff --git a/_dev/tstclnt/Dockerfile b/_dev/tstclnt/Dockerfile new file mode 100644 index 0000000..530be04 --- /dev/null +++ b/_dev/tstclnt/Dockerfile @@ -0,0 +1,41 @@ +FROM buildpack-deps + +RUN hg clone https://hg.mozilla.org/projects/nspr +RUN hg clone https://hg.mozilla.org/projects/nss + +ENV USE_64=1 NSS_ENABLE_TLS_1_3=1 +# Incremental build snapshot disabled as dependencies don't seem to be solid: +# the same value changed in a header file would apply to one .c file and not another +# RUN cd nss && make nss_build_all + +# Draft 15 +# ARG REVISION=c483e5f9e0bc + +# Draft 16 +# ARG REVISION=3e7b53b18112 + +# Draft 18 +ARG REVISION=b6dfef6d0ff0 + +RUN cd nss && hg pull +RUN cd nss && hg checkout -C $REVISION + +ADD *.patch ./ +RUN for p in *.patch; do patch -p1 -d nss < $p; done + +RUN cd nss && make nss_build_all + +# ENV HOST=localhost +# RUN cd nss/tests/ssl_gtests && ./ssl_gtests.sh + +RUN cd nss && make install + +RUN mv /dist/$(uname -s)$(uname -r | cut -f 1-2 -d . -)_$(uname -m)_${CC:-cc}_glibc_PTH_64_$([ -n "$BUILD_OPT" ] && echo OPT || echo DBG).OBJ /dist/OBJ-PATH + +ENV LD_LIBRARY_PATH=/dist/OBJ-PATH/lib + +ENV SSLTRACE=100 SSLDEBUG=100 + +ADD httpreq.txt /httpreq.txt +ADD run.sh /run.sh +ENTRYPOINT ["/run.sh"] diff --git a/_dev/tstclnt/httpreq.txt b/_dev/tstclnt/httpreq.txt new file mode 100644 index 0000000..e4e6ac1 --- /dev/null +++ b/_dev/tstclnt/httpreq.txt @@ -0,0 +1,5 @@ +GET / HTTP/1.1 +Host: example.com +Connection: close + + diff --git a/_dev/tstclnt/poll.patch b/_dev/tstclnt/poll.patch new file mode 100644 index 0000000..b7f92bc --- /dev/null +++ b/_dev/tstclnt/poll.patch @@ -0,0 +1,37 @@ +diff -r 15c6a01b9fe8 cmd/tstclnt/tstclnt.c +--- a/cmd/tstclnt/tstclnt.c Fri Jun 10 18:34:00 2016 +0100 ++++ b/cmd/tstclnt/tstclnt.c Thu Jun 16 16:26:29 2016 +0100 +@@ -713,7 +713,6 @@ + return NSS_GetClientAuthData(arg, socket, caNames, pRetCert, pRetKey); + } + +-#if defined(WIN32) || defined(OS2) + void + thread_main(void *arg) + { +@@ -746,7 +745,6 @@ + PR_Close(ps); + } + +-#endif + + static void + printHostNameAndAddr(const char *host, const PRNetAddr *addr) +@@ -1545,7 +1543,8 @@ + npds = 2; + std_out = PR_GetSpecialFD(PR_StandardOutput); + +-#if defined(WIN32) || defined(OS2) ++ // Enabled PR_Poll compatibility mode for running in docker run. (sigh). ++ + /* PR_Poll cannot be used with stdin on Windows or OS/2. (sigh). + ** But use of PR_Poll and non-blocking sockets is a major feature + ** of this program. So, we simulate a pollable stdin with a +@@ -1573,7 +1572,6 @@ + goto done; + } + } +-#endif + + if (serverCertAuth.testFreshStatusFromSideChannel) { + SSL_ForceHandshake(s); diff --git a/_dev/tstclnt/run.sh b/_dev/tstclnt/run.sh new file mode 100755 index 0000000..8ea9600 --- /dev/null +++ b/_dev/tstclnt/run.sh @@ -0,0 +1,8 @@ +#! /bin/bash + +IFS=':' read -ra ADDR <<< "$1" +shift +HOST="${ADDR[0]}" +PORT="${ADDR[1]}" + +exec /dist/OBJ-PATH/bin/tstclnt -D -V tls1.3:tls1.3 -o -O -h $HOST -p $PORT -v "$@" < /httpreq.txt