diff --git a/cmd/util/ech.go b/cmd/util/ech.go index 32a93e8..2e457e8 100644 --- a/cmd/util/ech.go +++ b/cmd/util/ech.go @@ -10,7 +10,7 @@ import ( ) const ( - ECHVersionDraft09 uint16 = 0xff09 // draft-ietf-tls-esni-09 + ECHVersionDraft09 uint16 = 0xfe09 // draft-ietf-tls-esni-09 ) // ECHConfigTemplate defines the parameters for generating an ECH config and @@ -83,7 +83,7 @@ func GenerateECHKey(template ECHConfigTemplate) (*ECHKey, error) { secretKey, err := sk.MarshalBinary() if err != nil { - return nil, fmt.Errorf("failed to marshal KEM secert key: %s", err) + return nil, fmt.Errorf("failed to marshal KEM secret key: %s", err) } var c cryptobyte.Builder diff --git a/impl-endpoints/cloudflare-go/runner.go b/impl-endpoints/cloudflare-go/runner.go index 73cff48..d16d6e9 100644 --- a/impl-endpoints/cloudflare-go/runner.go +++ b/impl-endpoints/cloudflare-go/runner.go @@ -3,6 +3,7 @@ package main import ( "crypto/tls" "crypto/x509" + "encoding/base64" "errors" "flag" "io/ioutil" @@ -11,66 +12,158 @@ import ( "os" ) -func createBaseClientConfig() (*tls.Config, error) { - certPool := x509.NewCertPool() +type testCase interface { + ClientConfig() (*tls.Config, error) + ClientConnectionHandler(*tls.Conn) error + ServerConfig() (*tls.Config, error) + ServerConnectionHandler(*tls.Conn) error +} + +var baseServerConfig, baseClientConfig *tls.Config + +func init() { + // Setup the base client configuration. pem, err := ioutil.ReadFile("/testdata/root.crt") if err != nil { - return nil, err + log.Fatal(err) } + + certPool := x509.NewCertPool() certPool.AppendCertsFromPEM(pem) - return &tls.Config{RootCAs: certPool}, nil -} + baseClientConfig = &tls.Config{ + RootCAs: certPool, + } -func createBaseServerConfig() (*tls.Config, error) { - cert, err := tls.LoadX509KeyPair("/testdata/example.crt", "/testdata/example.key") + // Setup the base server configuration. + serverCert, err := tls.LoadX509KeyPair( + "/testdata/example.crt", + "/testdata/example.key", + ) if err != nil { - return nil, err + log.Fatal(err) } - return &tls.Config{Certificates: []tls.Certificate{cert}}, nil -} -type testCase interface { - ClientConfig() (*tls.Config, error) - ClientConnectionHandler(*tls.Conn) error - ServerConfig() (*tls.Config, error) - ServerConnectionHandler(*tls.Conn) error -} + clientFacingCert, err := tls.LoadX509KeyPair( + "/testdata/client_facing.crt", + "/testdata/client_facing.key", + ) + if err != nil { + log.Fatal(err) + } -type delegatedCredentialTestCase struct { + baseServerConfig = &tls.Config{ + Certificates: []tls.Certificate{ + serverCert, + clientFacingCert, + }, + } } -func (c delegatedCredentialTestCase) ClientConfig() (*tls.Config, error) { - config, err := createBaseClientConfig() - if err != nil { - return nil, err - } +type testCaseDC struct{} +func (t testCaseDC) ClientConfig() (*tls.Config, error) { + config := baseClientConfig.Clone() config.SupportDelegatedCredential = true return config, nil } -func (c delegatedCredentialTestCase) ClientConnectionHandler(conn *tls.Conn) error { +func (t testCaseDC) ServerConfig() (*tls.Config, error) { + config := baseClientConfig.Clone() + return config, nil +} + +func (t testCaseDC) ClientConnectionHandler(conn *tls.Conn) error { if conn.ConnectionState().VerifiedDC == nil { return errors.New("Failed to verify a delegated credential") } return nil } -func (c delegatedCredentialTestCase) ServerConfig() (*tls.Config, error) { - config, err := createBaseServerConfig() +func (t testCaseDC) ServerConnectionHandler(conn *tls.Conn) error { + // TODO + return errors.New("NOT IMPLEMENTED") +} + +type echTestResult struct { + serverStatus tls.EXP_EventECHServerStatus +} + +func (r *echTestResult) eventHandler(event tls.EXP_Event) { + switch e := event.(type) { + case tls.EXP_EventECHServerStatus: + r.serverStatus = e + } +} + +type testCaseECHAccept struct{} + +func (t testCaseECHAccept) ClientConfig() (*tls.Config, error) { + base64ECHConfigs, err := ioutil.ReadFile("/testdata/ech_configs") if err != nil { return nil, err } + + rawECHConfigs, err := base64.StdEncoding.DecodeString(string(base64ECHConfigs)) + if err != nil { + return nil, err + } + + echConfigs, err := tls.UnmarshalECHConfigs(rawECHConfigs) + if err != nil { + return nil, err + } + + config := baseClientConfig.Clone() + config.ClientECHConfigs = echConfigs + config.ECHEnabled = true return config, nil } -func (c delegatedCredentialTestCase) ServerConnectionHandler(conn *tls.Conn) error { - // TODO - return errors.New("NOT IMPLEMENTED") +func (t testCaseECHAccept) ServerConfig() (*tls.Config, error) { + base64ECHKeys, err := ioutil.ReadFile("/testdata/ech_key") + if err != nil { + return nil, err + } + + rawECHKeys, err := base64.StdEncoding.DecodeString(string(base64ECHKeys)) + if err != nil { + return nil, err + } + + echKeys, err := tls.EXP_UnmarshalECHKeys(rawECHKeys) + if err != nil { + return nil, err + } + + echProvider, err := tls.EXP_NewECHKeySet(echKeys) + if err != nil { + return nil, err + } + + config := baseServerConfig.Clone() + config.ServerECHProvider = echProvider + config.ECHEnabled = true + return config, nil +} + +func (t testCaseECHAccept) connectionHandler(conn *tls.Conn) error { + if !conn.ConnectionState().ECHAccepted { + return errors.New("ECH not accepted") + } + return nil +} + +func (t testCaseECHAccept) ClientConnectionHandler(conn *tls.Conn) error { + return t.connectionHandler(conn) +} + +func (t testCaseECHAccept) ServerConnectionHandler(conn *tls.Conn) error { + return t.connectionHandler(conn) } var testCaseHandlers = map[string]testCase{ - "dc": delegatedCredentialTestCase{}, + "dc": testCaseDC{}, + "ech-accept": testCaseECHAccept{}, } func doClient(t testCase) error { @@ -84,8 +177,8 @@ func doClient(t testCase) error { return err } defer c.Close() - log.Print("Handshake completed") + log.Print("Handshake completed") return t.ClientConnectionHandler(c) } @@ -113,8 +206,8 @@ func doServer(t testCase) error { return err } defer s.Close() - log.Print("Handshake completed") + log.Print("Handshake completed") return t.ServerConnectionHandler(s) } @@ -125,7 +218,7 @@ func main() { handler, ok := testCaseHandlers[*testCase] if !ok { - // Skip this test case + // Skip this test case. os.Exit(64) }