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

Clean up testdata generation #19

Merged
merged 1 commit into from
Jan 7, 2021
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
6 changes: 2 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
.*.swp
certs/
cert-tool
cert-tool-src/cert-tool-src
*.pem
bin/
testdata/
30 changes: 19 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
CERT_TOOL_FILES = $(wildcard cert-tool-src/*.go)
TESTDATA_DIR = testdata
BIN_DIR = bin
UTIL = ${BIN_DIR}/util
UTIL_FILES = $(wildcard cmd/util/*.go)

cert-tool: $(CERT_TOOL_FILES)
go build -o cert-tool $^
util: $(CERT_TOOL_FILES)
mkdir -p ${BIN_DIR}
go build -o ${UTIL} ./cmd/util/...

.PHONY: certs
certs: cert-tool
rm -rf certs && mkdir certs
./cert-tool -make-root -out certs/rootCA.pem -key-out certs/rootCA.key
./cert-tool -make-intermediate -cert-in certs/rootCA.pem -key-in certs/rootCA.key -out certs/server.cert -key-out certs/server.key

dc: certs/server.cert certs/server.key cert-tool
./cert-tool -make-dc -cert-in certs/server.cert -key-in certs/server.key -out certs/dc.txt
.PHONY: testdata
testdata: util
mkdir -p ${TESTDATA_DIR}
${UTIL} -make-root -out ${TESTDATA_DIR}/root.crt -key-out ${TESTDATA_DIR}/root.key -host root.com
${UTIL} -make-intermediate -cert-in ${TESTDATA_DIR}/root.crt -key-in ${TESTDATA_DIR}/root.key -out ${TESTDATA_DIR}/example.crt -key-out ${TESTDATA_DIR}/example.key -host example.com
${UTIL} -make-intermediate -cert-in ${TESTDATA_DIR}/root.crt -key-in ${TESTDATA_DIR}/root.key -out ${TESTDATA_DIR}/client_facing.crt -key-out ${TESTDATA_DIR}/client_facing.key -host client-facing.com
${UTIL} -make-dc -cert-in ${TESTDATA_DIR}/example.crt -key-in ${TESTDATA_DIR}/example.key -out ${TESTDATA_DIR}/dc.txt
${UTIL} -make-ech -cert-in ${TESTDATA_DIR}/client_facing.crt -out ${TESTDATA_DIR}/ech_configs -key-out ${TESTDATA_DIR}/ech_key

clean:
rm -fr ${BIN_DIR}
rm -fr ${TESTDATA_DIR}

clean-docker:
docker builder prune
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ repository is in your $GOPATH (e.g.,
~/go/src/github.com/xvzcf/tls-interop-runner).

```
make certs
make dc
make testdata
```

You're now ready to run tests. The test case is also specified by setting an
Expand Down
128 changes: 0 additions & 128 deletions cert-tool-src/cli.go

This file was deleted.

File renamed without changes.
60 changes: 0 additions & 60 deletions cert-tool-src/ech.go → cmd/util/ech.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
package main

import (
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"

"golang.org/x/crypto/cryptobyte"

Expand All @@ -19,60 +13,6 @@ const (
ECHVersionDraft09 uint16 = 0xff09 // draft-ietf-tls-esni-09
)

// makeECHKey generates an ECH config and corresponding key, writing the key to
// outKeyPath and the config to outPath. The config is encoded as an ECHConfigs
// structure as specified by draft-ietf-tls-esni-09 (i.e., it is prefixed by
// 16-bit integer that encodes its length). This is the format as it is consumed
// by the client.
//
// The first DNS name of certificate inCertPath is used as the ECH config's
// public name. The remaining parameters of the ECH config are specified by the
// template.
func makeECHKey(template ECHConfigTemplate, inCertPath, outPath, outKeyPath string) {
certParseErrMsg := "failed to parse input certificate"
keyGenErrMsg := "failed to generate ECH key"

// Load the certificate of the client-facing server.
clientFacingCertPEMBlock, err := ioutil.ReadFile(filepath.Join(inCertPath))
fatalIfErr(err, certParseErrMsg)
clientFacingCertDERBlock, _ := pem.Decode(clientFacingCertPEMBlock)
if clientFacingCertDERBlock == nil || clientFacingCertDERBlock.Type != "CERTIFICATE" {
fatalIfErr(errors.New("PEM decoding failed"), certParseErrMsg)
}
clientFacingCert, err := x509.ParseCertificate(clientFacingCertDERBlock.Bytes)
fatalIfErr(err, certParseErrMsg)

// Generate the ECH config and corresponding key, using the first DNS name
// specified by the client-facing certificate as the public name.
//
// TODO(cjpatton): Assert that clientFAcingCert.DNSNames[0] is a valid SNI
// (e.g., not something like *.example.com).
if len(clientFacingCert.DNSNames) == 0 {
fatalIfErr(errors.New("input certificate does not specify a DNS name"), keyGenErrMsg)
}
template.PublicName = clientFacingCert.DNSNames[0]
key, err := GenerateECHKey(template)
fatalIfErr(err, keyGenErrMsg)

// Write the key to disk.
outKey, err := os.OpenFile(outKeyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
fatalIfErr(err, keyGenErrMsg)
defer outKey.Close()
outKeyEncoder := base64.NewEncoder(base64.StdEncoding, outKey)
defer outKeyEncoder.Close()
_, err = outKeyEncoder.Write(key.Marshal())
fatalIfErr(err, keyGenErrMsg)

// Write the config to disk.
out, err := os.Create(outPath)
fatalIfErr(err, keyGenErrMsg)
defer out.Close()
outEncoder := base64.NewEncoder(base64.StdEncoding, out)
defer outEncoder.Close()
_, err = outEncoder.Write(MarshalECHConfigs([]ECHKey{*key}))
fatalIfErr(err, keyGenErrMsg)
}

// ECHConfigTemplate defines the parameters for generating an ECH config and
// corresponding key.
type ECHConfigTemplate struct {
Expand Down
59 changes: 58 additions & 1 deletion cert-tool-src/cert.go → cmd/util/make.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"log"
"math/big"
"net"
"net/mail"
"net/url"
"os"
"path/filepath"
)

Expand Down Expand Up @@ -77,7 +80,7 @@ func makeRootCertificate(config *Config, outPath string, outKeyPath string) {
fatalIfErr(err, "failed to encode CA key")

err = ioutil.WriteFile(outKeyPath, pem.EncodeToMemory(
&pem.Block{Type: "PRIVATE KEY", Bytes: privDER}), 0400)
&pem.Block{Type: "PRIVATE KEY", Bytes: privDER}), 0600)
fatalIfErr(err, "failed to write CA key")

err = ioutil.WriteFile(outPath, pem.EncodeToMemory(
Expand Down Expand Up @@ -260,3 +263,57 @@ func makeDelegatedCredential(config *Config, parentSignConfig *Config, inCertPat
fatalIfErr(err, "failed to save DC")
log.Printf("\nThe generated DC (format: DC, privkey) is at \"%s\" \n\n", outPath)
}

// makeECHKey generates an ECH config and corresponding key, writing the key to
// outKeyPath and the config to outPath. The config is encoded as an ECHConfigs
// structure as specified by draft-ietf-tls-esni-09 (i.e., it is prefixed by
// 16-bit integer that encodes its length). This is the format as it is consumed
// by the client.
//
// The first DNS name of certificate inCertPath is used as the ECH config's
// public name. The remaining parameters of the ECH config are specified by the
// template.
func makeECHKey(template ECHConfigTemplate, inCertPath, outPath, outKeyPath string) {
certParseErrMsg := "failed to parse input certificate"
keyGenErrMsg := "failed to generate ECH key"

// Load the certificate of the client-facing server.
clientFacingCertPEMBlock, err := ioutil.ReadFile(filepath.Join(inCertPath))
fatalIfErr(err, certParseErrMsg)
clientFacingCertDERBlock, _ := pem.Decode(clientFacingCertPEMBlock)
if clientFacingCertDERBlock == nil || clientFacingCertDERBlock.Type != "CERTIFICATE" {
fatalIfErr(errors.New("PEM decoding failed"), certParseErrMsg)
}
clientFacingCert, err := x509.ParseCertificate(clientFacingCertDERBlock.Bytes)
fatalIfErr(err, certParseErrMsg)

// Generate the ECH config and corresponding key, using the first DNS name
// specified by the client-facing certificate as the public name.
//
// TODO(cjpatton): Assert that clientFAcingCert.DNSNames[0] is a valid SNI
// (e.g., not something like *.example.com).
if len(clientFacingCert.DNSNames) == 0 {
fatalIfErr(errors.New("input certificate does not specify a DNS name"), keyGenErrMsg)
}
template.PublicName = clientFacingCert.DNSNames[0]
key, err := GenerateECHKey(template)
fatalIfErr(err, keyGenErrMsg)

// Write the key to disk.
outKey, err := os.OpenFile(outKeyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
fatalIfErr(err, keyGenErrMsg)
defer outKey.Close()
outKeyEncoder := base64.NewEncoder(base64.StdEncoding, outKey)
defer outKeyEncoder.Close()
_, err = outKeyEncoder.Write(key.Marshal())
fatalIfErr(err, keyGenErrMsg)

// Write the config to disk.
out, err := os.Create(outPath)
fatalIfErr(err, keyGenErrMsg)
defer out.Close()
outEncoder := base64.NewEncoder(base64.StdEncoding, out)
defer outEncoder.Close()
_, err = outEncoder.Write(MarshalECHConfigs([]ECHKey{*key}))
fatalIfErr(err, keyGenErrMsg)
}
File renamed without changes.
Loading