Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cloudflare-go client <-> boringssl server ech-accept works. #54

Merged
merged 1 commit into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ make runner
2. Tests are run with `docker-compose`, with the artifacts copied into a virtual
volume. To run a test with, say, Cloudflare-Go as server and Boringssl as client,
you must first build the necessary docker images, and run the appropiate
test (for example, the delegated credentials one):
test (for example, `ech-accept`):

```
./bin/runner --client=cloudflare-go --server=boringssl --build --testcase=dc
./bin/runner --client=cloudflare-go --server=boringssl --build --testcase=ech-accept
```
6 changes: 0 additions & 6 deletions cmd/runner/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,4 @@ var endpoints = map[string]endpoint{
client: true,
server: true,
},
"tls-attacker": {
name: "tls-attacker",
regression: true,
client: true,
server: false,
},
}
2 changes: 1 addition & 1 deletion cmd/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func doBuildEndpoints(client endpoint, server endpoint, verbose bool) error {
}

func doTestcase(t testcase, testcaseName string, client endpoint, server endpoint, verbose bool, allTestsMode bool) error {
log.Println("\nTesting: " + testcaseName)
log.Println("Testing: " + testcaseName)
var result resultType

err := t.setup(verbose)
Expand Down
239 changes: 238 additions & 1 deletion cmd/runner/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"strings"
"time"

"github.com/cloudflare/circl/hpke"
"github.com/xvzcf/tls-interop-runner/internal/pcap"
"github.com/xvzcf/tls-interop-runner/internal/utils"
)
Expand Down Expand Up @@ -89,10 +90,15 @@ type testcaseDC struct {
}

func (t *testcaseDC) setup(verbose bool) error {
err := os.MkdirAll(testInputsDir, os.ModePerm)
err := os.RemoveAll(testInputsDir)
if err != nil {
return err
}
err = os.MkdirAll(testInputsDir, os.ModePerm)
if err != nil {
return err
}

err = os.RemoveAll(testOutputsDir)
if err != nil {
return err
Expand Down Expand Up @@ -278,8 +284,239 @@ func (t *testcaseDC) teardown(moveOutputs bool) error {
return nil
}

type testcaseECHAccept struct {
name string
timeout time.Duration
outputDir string
logger *log.Logger
logFile *os.File
}

func (t *testcaseECHAccept) setup(verbose bool) error {
err := os.RemoveAll(testInputsDir)
if err != nil {
return err
}
err = os.MkdirAll(testInputsDir, os.ModePerm)
if err != nil {
return err
}

err = os.RemoveAll(testOutputsDir)
if err != nil {
return err
}
err = os.MkdirAll(testOutputsDir, os.ModePerm)
if err != nil {
return err
}
runLog, err := os.Create(filepath.Join(testOutputsDir, "run-log.txt"))
if err != nil {
runLog.Close()
return err
}
if verbose {
t.logger = log.New(io.MultiWriter(os.Stdout, runLog),
"",
log.Ldate|log.Ltime|log.Lshortfile)
} else {
t.logger = log.New(io.Writer(runLog),
"",
log.Ldate|log.Ltime|log.Lshortfile)
}

rootSignatureAlgorithm, err := utils.MakeRootCertificate(
&utils.Config{
Hostnames: []string{"root.com"},
ValidFrom: time.Now(),
ValidFor: 365 * 25 * time.Hour,
},
filepath.Join(testInputsDir, "root.crt"),
filepath.Join(testInputsDir, "root.key"),
)
if err != nil {
runLog.Close()
return err
}
t.logger.Printf("Root certificate algorithm: 0x%X\n", rootSignatureAlgorithm)

intermediateSignatureAlgorithm, err := utils.MakeIntermediateCertificate(
&utils.Config{
Hostnames: []string{"example.com"},
ValidFrom: time.Now(),
ValidFor: 365 * 25 * time.Hour,
ForDC: true,
},
filepath.Join(testInputsDir, "root.crt"),
filepath.Join(testInputsDir, "root.key"),
filepath.Join(testInputsDir, "example.crt"),
filepath.Join(testInputsDir, "example.key"),
)
if err != nil {
runLog.Close()
return err
}
t.logger.Printf("example.com intermediate certificate algorithm: 0x%X\n", intermediateSignatureAlgorithm)

intermediateSignatureAlgorithm, err = utils.MakeIntermediateCertificate(
&utils.Config{
Hostnames: []string{"client-facing.com"},
ValidFrom: time.Now(),
ValidFor: 365 * 25 * time.Hour,
ForDC: true,
},
filepath.Join(testInputsDir, "root.crt"),
filepath.Join(testInputsDir, "root.key"),
filepath.Join(testInputsDir, "client-facing.crt"),
filepath.Join(testInputsDir, "client-facing.key"),
)
if err != nil {
runLog.Close()
return err
}
t.logger.Printf("client-facing.com intermediate certificate algorithm: 0x%X\n", intermediateSignatureAlgorithm)

err = utils.MakeECHKey(
utils.ECHConfigTemplate{
Id: 123, // This is chosen at random by the client-facing server.
PublicName: "client-facing.com",
Version: utils.ECHVersionDraft13,
KemId: uint16(hpke.KEM_X25519_HKDF_SHA256),
KdfIds: []uint16{
uint16(hpke.KDF_HKDF_SHA256),
},
AeadIds: []uint16{
uint16(hpke.AEAD_AES128GCM),
},
MaximumNameLength: 0,
},
filepath.Join(testInputsDir, "ech_configs"),
filepath.Join(testInputsDir, "ech_key"),
)
if err != nil {
runLog.Close()
return err
}

t.logFile = runLog
return nil

}

func (t *testcaseECHAccept) run(client endpoint, server endpoint) (result resultType, err error) {
pc, _, _, _ := runtime.Caller(0)
fn := runtime.FuncForPC(pc)

cmd := exec.Command("docker-compose", "up",
"-V",
"--no-build",
"--abort-on-container-exit")

env := os.Environ()
env = append(env, fmt.Sprintf("SERVER=%s", server.name))
env = append(env, fmt.Sprintf("CLIENT=%s", client.name))
env = append(env, fmt.Sprintf("TESTCASE=%s", t.name))
// SERVER_SRC and CLIENT_SRC should not be needed, since the images
// should be built and tagged by this point. They're just set to suppress
// unset variable warnings by docker-compose.
env = append(env, "SERVER_SRC=\"\"")
env = append(env, "CLIENT_SRC=\"\"")
cmd.Env = env

var cmdOut bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &cmdOut
cmd.Stderr = &stderr

err = cmd.Start()
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
result = resultError
goto runUnsuccessful
}

err = waitWithTimeout(cmd, t.timeout)
if err != nil {
if strings.Contains(err.Error(), "exit status 64") {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
result = resultUnsupported
goto runUnsuccessful
}
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
result = resultFailure
goto runUnsuccessful
}

t.logger.Println("OUT: " + cmdOut.String())
t.logger.Printf("%s completed without error.\n", fn.Name())
return resultSuccess, nil

runUnsuccessful:
t.logger.Println("OUT: " + cmdOut.String())
t.logger.Println("ERROR: " + fmt.Sprint(err) + ": " + stderr.String())
return result, err
}

func (t *testcaseECHAccept) verify() (resultType, error) {
pc, _, _, _ := runtime.Caller(0)
fn := runtime.FuncForPC(pc)

err := pcap.FindTshark()
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
t.logger.Println(err)
return resultError, err
}

pcapPath := filepath.Join(testOutputsDir, "client_node_trace.pcap")
keylogPath := filepath.Join(testOutputsDir, "client_keylog")
transcript, err := pcap.Parse(pcapPath, keylogPath)
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
t.logger.Println(err)
return resultFailure, err
}

err = pcap.Validate(transcript, t.name)
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
t.logger.Println(err)
return resultFailure, err
}

t.logger.Printf("%s completed without error.\n", fn.Name())
return resultSuccess, nil
}

func (t *testcaseECHAccept) teardown(moveOutputs bool) error {
pc, _, _, _ := runtime.Caller(0)
fn := runtime.FuncForPC(pc)

t.logFile.Close()

if moveOutputs {
destDir := filepath.Join("generated", fmt.Sprintf("%s-out", t.name))
err := os.RemoveAll(destDir)
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
t.logger.Println(err)
return err
}
err = os.Rename(testOutputsDir, destDir)
if err != nil {
err = &errorWithFnName{err: err.Error(), fnName: fn.Name()}
t.logger.Println(err)
return err
}
}
return nil
}

var testcases = map[string]testcase{
"dc": &testcaseDC{
name: "dc",
timeout: 100 * time.Second},
"ech-accept": &testcaseECHAccept{
name: "ech-accept",
timeout: 100 * time.Second},
}
3 changes: 2 additions & 1 deletion cmd/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,9 @@ func main() {
} else if *makeECH {
err := utils.MakeECHKey(
utils.ECHConfigTemplate{
Id: 123,
PublicName: *hostName,
Version: utils.ECHVersionDraft09,
Version: utils.ECHVersionDraft13,
KemId: uint16(hpke.KEM_X25519_HKDF_SHA256),
KdfIds: []uint16{
uint16(hpke.KDF_HKDF_SHA256),
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

module github.com/xvzcf/tls-interop-runner

go 1.15
go 1.16

require (
github.com/cloudflare/circl v1.0.1-0.20210104183656-96a0695de3c3
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
github.com/cloudflare/circl v1.0.1-0.20210909160006-8e341dceb53a
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
)
26 changes: 13 additions & 13 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
github.com/cloudflare/circl v1.0.1-0.20210104183656-96a0695de3c3 h1:tpTW2GMi0DOdFJswbXNG6f45rOAgowhgPdofAWDKLwI=
github.com/cloudflare/circl v1.0.1-0.20210104183656-96a0695de3c3/go.mod h1:l2CvGr3DNS9Egif8pwQqJ45Ci9Y/PPs0XJHTcRKbGBQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f h1:QdHQnPce6K4XQewki9WNbG5KOROuDzqO3NaYjI1cXJ0=
golang.org/x/sys v0.0.0-20201211090839-8ad439b19e0f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cloudflare/circl v1.0.1-0.20210909160006-8e341dceb53a h1:T7NhgEceBBRSlVcNHzPfT3MY39Kn77Fnfpoi6ORcuf0=
github.com/cloudflare/circl v1.0.1-0.20210909160006-8e341dceb53a/go.mod h1:wqo+yhCGS0T5Ldpb0f4hdJqVGwsEBYDE3MrO6W/RACc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
8 changes: 5 additions & 3 deletions impl-endpoints/boringssl/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ FROM golang:latest AS builder

RUN apt-get update && \
apt-get install -y git cmake ninja-build perl && \
git clone --branch dc-spec-update https://github.com/xvzcf/boringssl /boringssl
git clone --branch master https://boringssl.googlesource.com/boringssl /boringssl

WORKDIR /boringssl
RUN git checkout aac1a2d0fb616cab6a331c2534f4b1b7b8aebfa6
RUN git checkout 295b31324f8c557dcd3c1c831857e33a7f23bc52

RUN mkdir /boringssl/build
WORKDIR /boringssl/build
Expand All @@ -21,11 +21,13 @@ RUN make
FROM ubuntu:20.04

RUN apt-get update && \
apt-get install -y net-tools tcpdump ethtool iproute2
apt-get install -y net-tools tcpdump ethtool iproute2 python3

COPY --from=builder /boringssl/build/tool/bssl /usr/bin/
COPY --from=builder /runner-src/runner /usr/bin/

COPY ech_key_converter.py /

COPY run_endpoint.sh /run_endpoint.sh
RUN chmod +x /run_endpoint.sh

Expand Down
Loading