Git Product home page Git Product logo

go's Introduction

๐Ÿšจ This fork is offered as-is, and without guarantees. It is expected that changes in the code, repository, and API occur in the future. We recommend to take caution before using this library in production.

cfgo

This is an experimental fork of Go, that patches the TLS stack, to support:

  1. Encrypted ClientHello (ECH)
  2. Post-quantum key agreement
  3. Delegated Credentials
  4. Post-quantum certificates.
  5. Configuraton of keyshares sent in ClientHello with tls.Config.ClientCurveGuess.

To use upstream Go and this fork with the same codebase, this fork sets the cfgo build tag.

Build

$ git clone https://github.com/cloudflare/go
$ cd go/src
$ ./make.bash

You can now use ../bin/go as you would regular go.

go's People

Contributors

4a6f656c avatar aclements avatar adg avatar agl avatar alexbrainman avatar bradfitz avatar cherrymui avatar cixtor avatar crawshaw avatar cuonglm avatar davecheney avatar dr2chase avatar dvyukov avatar filosottile avatar findleyr avatar griesemer avatar ianlancetaylor avatar josharian avatar ken avatar mdempsky avatar minux avatar mknyszek avatar mvdan avatar nigeltao avatar prattmic avatar randall77 avatar robpike avatar rsc avatar thanm avatar tklauser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go's Issues

crypto/tls: Vet interaction between ECH and PSK

We may have a bug in crypto/tls that would be triggered by ECH rejection when the server supports PSK. The bug would cause the handshake to fail. I will investigate soon, unless someone gets there first. The temporary fix should be as simple as disabling ECH+PSK. It's likely that the spec will be changed in a way that allows us to properly patch this problem without a major refactor. See tlswg/draft-ietf-tls-esni#399.

Establish a review process

TODO

  1. [DONE] Add CODEOWNERS file
  2. [DONE] Write up the process in the Wiki
  3. [DONE] Create cf-tls-1000 branch for tls-1000 releases. (Blocked by #55.)

Define an API for DCs

Currently, there is a callback for using DC: GetDelegatedCredential. This can be improved to:

  • Use the GetCertificate and GetCertificateClient callbacks to return the DCs as part of the Certificate structure
  • Allow the possibility of returning a list of DCs: the appropriate DC will be chosen by using the advertise signature algorithm on the ClientHello/Certificate Request extension.
  • Refactor the DC tests.

Incorrect PublicKeyAlgorithm.String() of x509.EdDilithium3 in parsed certificate

Description:

The ParseCertificate function is generating a certificate with incorrect PublicKeyAlgorithm.String() values.

Steps to reproduce:

  1. Run the TestCreateCert test in the app_test.go file.
  2. Observe the test failure with the error message indicating that the PublicKeyAlgorithm.String() values do not match the expected values.

Expected result:

The ParseCertificate function should generate a certificate with PublicKeyAlgorithm.String() set to Ed448-Dilithium3.

Actual result:

The ParseCertificate function generates a certificate with PublicKeyAlgorithm.String() set to Ed25519-Dilithium3.

Code snippet:

The relevant code snippet is:

https://github.com/cloudflare/circl/blob/75b28edc25ec569e6353a2b944b0b83d48a9c2e8/sign/eddilithium3/eddilithium.go#L31

// PublicKey is the type of an EdDilithium3 public key.
type PublicKey struct {
	e ed448.PublicKey
	d mode3.PublicKey
}

app.go

func CreateCert() ([]byte, error) {
	scheme := x509.CirclSchemeByPublicKeyAlgorithm(x509.EdDilithium3)
	pk, sk, err := scheme.GenerateKey()
	if err != nil {
		return nil, err
	}
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	template := &x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Foo 1983"},
		},
		NotBefore:             notBefore,
		NotAfter:              notAfter,
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	cert, err := x509.CreateCertificate(rand.Reader, template, template, pk, sk)
	return cert, err
}

app_test.go

func TestCreateCert(t *testing.T) {
    assert := assert.New(t)
    cert, _ := CreateCert()
    parsedCert, _ := x509.ParseCertificate(cert)
    assert.Equal("Foo 1983", parsedCert.Subject.Organization[0], "Organization should be Foo 1983")
    assert.Equal(x509.SignatureAlgorithm(17), parsedCert.SignatureAlgorithm, "SignatureAlgorithm should be x509.SignatureAlgorithm(17)")
    assert.Equal("Ed448-Dilithium3", parsedCert.SignatureAlgorithm.String(), "SignatureAlgorithm should be Ed448-Dilithium3")
    assert.Equal(x509.PublicKeyAlgorithm(5), parsedCert.PublicKeyAlgorithm, "PublicKeyAlgorithm should be x509.PublicKeyAlgorithm(5)")
    assert.Equal("Ed448-Dilithium3", parsedCert.PublicKeyAlgorithm.String(), "PublicKeyAlgorithm should be Ed448-Dilithium3")
}

go test

--- FAIL: TestCreateCert (0.00s)
                Error:          Not equal: 
                                expected: "Ed448-Dilithium3"
                                actual  : "Ed25519-Dilithium3"
                Test:           TestCreateCert
                Messages:       PublicKeyAlgorithm should be Ed448-Dilithium3

Kyber example incompatible with Google's kex implementation

Hey there ๐Ÿ‘‹

I have been playing around with the example shared in the article Experiment with post-quantum cryptography today and have noticed something unexpected: when I try to establish a TLS connection to a website with Kyber as the kex, it seems to only work on Cloudflare-enabled sites.

When I try changing the requested URL to something like https://google.com, it outputs the following:

HelloRetryRequest
Used 29

But when I try something on Cloudflare, like cloudflare.com or gitlab.com, I get the following, as expected:

Used X25519Kyber512Draft00
Example code used

package main

import (
    "context"
    "crypto/tls"
    "fmt"
    "net/http"
)

func main() {
    req, err := http.NewRequestWithContext(
        context.WithValue(
            context.Background(),
            tls.CFEventHandlerContextKey{},
            func(ev tls.CFEvent) {
                switch e := ev.(type) {
                case tls.CFEventTLS13HRR:
                    fmt.Printf("HelloRetryRequest\n")
                case tls.CFEventTLS13NegotiatedKEX:
                    switch e.KEX {
                    case tls.X25519Kyber512Draft00:
                        fmt.Printf("Used X25519Kyber512Draft00\n")
                    default:
                        fmt.Printf("Used %d\n", e.KEX)
                    }
                }
            },
        ),
        "GET",
        "https://google.com",
        nil,
    )
    if err != nil {
        panic(err)
    }

    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
        CurvePreferences: []tls.CurveID{tls.X25519Kyber512Draft00, tls.X25519},
    }

    if _, err = (&http.Client{}).Do(req); err != nil {
        fmt.Println(err)
    }
}

When trying to request these URLs inside of Chrome and Firefox, both seem to correctly use Kyber as well. This also works correctly in upstream boringssl (not the CF fork).

image

I was not able to verify this against any other services besides Google and Cloudflare, since those seem to be the biggest current adopters.

Update to Go 1.4.3

Go 1.4.3 patches some security vulnerabilities in reverse proxy servers that use net/http. Any possibility of patching your fork (at least in some 1.4.3 branch or tag)?

Is it possible to enable ECH in a forward proxy?

My idea is to modify the ClientHello to enable ECH when the proxy receives it from the client and then forward it to the server.

First, I tried to read and forward the ClientHello, which worked successfully, and the client's HTTP request succeeded.

func EnableProxyEch(clientConn, serverConn net.Conn,tlsConfig *Config) error{
	cc :=Server(clientConn,nil)
	msg, err := cc.readHandshake(nil)
	if err != nil {
		fmt.Println("read from client error\n")
		return fmt.Errorf("read handshake error:%s",err.Error())
	}
	clientHello, ok := msg.(*clientHelloMsg)
	if !ok {
		return fmt.Errorf("cast error")
	}

	sc:=Client(serverConn,tlsConfig)
	if _, err = sc.writeHandshakeRecord(clientHello, nil); err != nil {
		return err
	}

	// transport clientConn <-> serverConn
	return nil
}

Next, I tried to modify and forward the ClientHello. However, the client (e.g., curl) reported an error:
error:0A000417:SSL routines::ssl/tls alert illegal parameter.

func EnableProxyEch(clientConn, serverConn net.Conn,tlsConfig *Config) error{
	cc :=Server(clientConn,nil)
	msg, err := cc.readHandshake(nil)
	if err != nil {
		fmt.Println("read from client error\n")
		return fmt.Errorf("read handshake error:%s",err.Error())
	}
	clientHello, ok := msg.(*clientHelloMsg)
	if !ok {
		return fmt.Errorf("cast error")
	}

	sc:=Client(serverConn,tlsConfig)

	// modify clientHello to enable ECH,cause client like curl error
	sc.didResume=false
	helloBase:=clientHello
	hello, _, err := sc.echOfferOrGrease(helloBase)
	if err != nil {
		return err
	}

	if _, err = sc.writeHandshakeRecord(hello, nil); err != nil {
		return err
	}

	// transport clientConn <-> serverConn
	return nil
}

Add hybrid KEMTLS

We need to add a version of a hybrid KEMTLS. This needs to:

  • Define an specification for how Hybrid KEMTLS works
  • Add the appropriate changes to the KEMTLS code.

Depends on #66

PQ cipher suites are not used even when specified in tls.Config

Even when pq cipher suites are explicitly specified in tls.Config:

	conf := &tls.Config{
		CipherSuites: []uint16{
			uint16(ctls.X25519Kyber768Draft00),
		},
	}

They won't be used in the TLS Client Hello due to the fact that these cipher suites aren't present in the cipherSuitesPreferenceOrder: https://github.com/cloudflare/go/blob/cf/src/crypto/tls/cipher_suites.go#L271

This happens because of this check: https://github.com/cloudflare/go/blob/cf/src/crypto/tls/handshake_client.go#L100

Would it be possible to add an option to use these new cipher suites in ClientHello?

Will it move to go1.5?

Hello there,

Thank you all for the amazing works!

As you know, go1.5 rc1 come out today, so is there any chance to move these patches to go1.5 branch?

UPDATE: I forked the offical golang/go repo then cherry-picked the cloudflare commits to it here, https://github.com/phuslu/go
but maintain a homemade repo is nightmare, hope that cloudflare/go is possible to rebase to go1.5 in near future.

Regards,
Phus

signatureSchemeForDelegatedCredential is unneccessary

signatureSchemeForDelegatedCredential returns the list of supported signature schemes for a delegated credential; however, per the spec, DCs are explicitly restricted to a single SignatureAlgorithm defined in the dc_cert_verify_algorithm field.
We can simply use dc_cert_verify_algorithm, rather than call this function.

Remove custom fields in tls.Config

quic-go uses qtls which requires a match between its data structures and the standard library to match. This includes tls.Config, tls.ConnectionState, tls.ClientHelloInfos, and some others. See https://github.com/quic-go/qtls-go1-20/blob/master/unsafe.go

It would be nice if we can reduce custom fields unless there is no other way. This can be done through contexts.

In commit 01665a5 ("crypto/tls: add CFControl parameter to Config"), we add a tls.Config#CFControl field to propagate information from the TLS handshake (tls.Config#GetConfigForClient) to a HTTP request handler (http.Request#TLS.CFControl). To replace this with contexts:

  1. Set http.Server#ConnContext to add an empty structure to the context of the connection.
  2. In tls.Config#GetConfigForClient, extract the previous structure pointer from the context through tls.ClientHelloInfos#Context and initialize it. Note that while modifications to the context itself are not propagated, any changes to the context value (a pointer to a structure) will be preserved. This is a crucial detail.
  3. In a HTTP handler, extract the structure pointer again from the context through http.Request#Context.

To demonstrate the above conversion:

type contextKey struct{ name string }

var controlContextKey = &contextKey{"connection-metadata"}

type ConnState struct {
	ExampleValue []byte
}

func main() {
	srv := http.Server{
		ConnContext: func(ctx context.Context, c net.Conn) context.Context {
			// 1. allocate context value in the connection context
			return context.WithValue(ctx, controlContextKey, &ConnState{})
		},
	}
	cert, err := tls.LoadX509KeyPair("example-cert.pem", "example-key.pem")
	if err != nil {
		log.Fatal(err)
	}
	tlsConfig := &tls.Config{
		GetConfigForClient: func(chi *tls.ClientHelloInfo) (*tls.Config, error) {
			// 2. initialize state in context value
			cs := chi.Context().Value(controlContextKey).(*ConnState)
			cs.ExampleValue = []byte("hello world\n")
			return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
		},
	}

	http.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
		// 3. extract value from context
		cs := req.Context().Value(controlContextKey).(*ConnState)
		rw.Write(cs.ExampleValue)
	})

	// Setup HTTPS server
	netListener, err := net.Listen("tcp", "localhost:4433")
	if err != nil {
		log.Fatal(err)
	}
	ln := tls.NewListener(netListener, tlsConfig)
	if err := srv.Serve(ln); err != http.ErrServerClosed {
		log.Fatal(err)
	}
}

I'll work on changes to the cf branch to remove the CFControl field and investigate how other fields can similarly be removed.

Templates for issues and PRs

#86 removes the boiler-plate templates for opening issues and PRs that we inherited from the upstreasm repository. The reason to remove these is they point the person submitting the issue or PR to Google's pipeline for reviewing changes. In the comments on that PR, @wbl and @claucece suggested that some of the material is useful for us. This issue addresses what the templates should say.

Implement delegated credentials

Basically, I'll divide this task on:

  • Review the two PRs over tls-tris that implemented delegated credentials
  • Make the first skeleton from DC work with TLS 1.2, to understand the golang API
  • Switch to implementing for TLS 1.3 as per draft:
    • Server Auth
    • Client Auth
  • Add tests and verify the command line param works
  • Add other schemes to DC
  • Generate draft test vectors

crypto/tls: Unit tests for ECH edge caes

@Lekensteyn suggested we add a unit test for asserting that the client-facing server rejects if the client sends GREASE ECH with a config id that matches a known config but which uses a different KEM algorithm: #95 (comment)

We might also want to check that it rejects when the KDF/AEAD algorithm pair isn't supported.

Licence

Hi,

What is the license of your AES-GCM implementation? Is it exclusively the Go license?

I'd love to merge it to Libsodium, but that project is using the ISC license, which is also a BSD-like license, but that might not be compatible with the Go license.

Verify tests for DC

Tests for DCs fail when running isolated, but they pass when invoked as a batch (i.e. go test -v -run=.)

What did you do?

$ cd src/crypto/tls
$ ../../../bin/go test -v -run=DC

What did you expect to see?

=== RUN   TestDCHandshakeServerAuth
--- PASS: TestDCHandshakeServerAuth (0.14s)
=== RUN   TestDCHandshakeClientAuth
--- PASS: TestDCHandshakeClientAuth (0.14s)
=== RUN   TestDCHandshakeClientAndServerAuth
--- PASS: TestDCHandshakeClientAndServerAuth (0.03s)

What did you see instead?

    delegated_credentials_test.go:592: test #1 dcCounter:1, (tls13: DC server and client support) fails: x509: certificate signed by unknown authority
    delegated_credentials_test.go:598: test #1 (tls13: DC server and client support) usedDC = false; expected true
    delegated_credentials_test.go:592: test #1 dcCounter:2, (tls13: DC server and client support) fails: x509: certificate signed by unknown authority
    delegated_credentials_test.go:598: test #1 (tls13: DC server and client support) usedDC = false; expected true
    delegated_credentials_test.go:592: test #1 dcCounter:3, (tls13: DC server and client support) fails: x509: certificate signed by unknown authority
    delegated_credentials_test.go:598: test #1 (tls13: DC server and client support) usedDC = false; expected true

Any of the improvements being submitted to Go main branch?

I would like to use the improvements but would rather not hand merge the changes with the current Go 1.6 tip code if some or most of the improvements is already taken in by Go.

Can you guys confirm or deny if any of the improvement made it to the official Go code?

crypto/tls: keyUsage tests exclusively for DigitalSignature flag

The tls.Config.KeyUsage field can contain several flags.
Currently, for generating a delegated credential extension, it tests that the KeyUsageDigitalSignature flags is enabled exclusively.

go/src/crypto/x509/x509.go

Lines 1789 to 1795 in 5ef1b90

// This extension is not critical
if template.KeyUsage == KeyUsageDigitalSignature && template.AllowDC && !template.IsCA && !oidInExtensions(oidExtensionDelegatedCredential, template.ExtraExtensions) {
ret[n].Id = oidExtensionDelegatedCredential
ret[n].Value, err = asn1.Marshal(asn1.NullRawValue)
if err != nil {
return
}

Shouldn't this
(template.KeyUsage == KeyUsageDigitalSignature)
be replaced by
(template.KeyUsage & KeyUsageDigitalSignature != 0)

i.e., only testing the flag is present, without baning from setting other flags in the same field.

DC tests don't validate certificates

In delegated_credentials_test.go TestDCHandshakeServerAuth sets clientConfig.InsecureSkipVerify = true. Because of how golang handles global state this is propagated to all later tests. This leads to test failures if the tests are run in a different order or individually.
This means that even if you put bit flips into the test certificate signatures the tests will still pass.

Update KEMTLS code

Given that dc are now of the cf branch, KEMTLS can be implemented there as well. The KEMTLS functionality is implemented in the cf-pq-kemtls branch but needs to be updated to the latest DC code.

The task consists of:

  • Updating KEMTLS code to the Go 1.16
  • Updating KEMTLS code to the latest DC code
  • Creating a parameter that allows the usage of KEMTLS and acts as a barrier so when it is set to false it cannot be used (for security purposes of TLS-1000).

Unable to use the keys generated with the CIRCL library

I'm not entirely sure why the following code isn't working as intended:

package main

import (
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"math/big"
	"os"
	"sort"
	"time"

	"github.com/cloudflare/circl/sign/eddilithium3"
)

func main() {

	pk, sk, err := eddilithium3.GenerateKey(nil)
	if err != nil {
		panic(err)
	}else{
		fmt.Printf("Created private key!\n")
	}
	
	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialNumber, err := rand.Int(sk.Public()rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
	if err != nil {
		panic(err)
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Bedis-Test-CA"},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
		IsCA:                  true,
	}

	// Erstellen des CA-Zertifikats
	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pk, sk)
	if err != nil {
		panic(err)
	} else {
		fmt.Printf("Created CA!\n")
	}

	// Speichern des CA-Zertifikats
	certOut, err := os.Create("ca.pem")
	if err != nil {
		panic(err)
	}else{
		fmt.Printf("Saved CA-File!\n")
	}
	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	certOut.Close()
	

}

Output:

x509: only RSA, ECDSA, Ed25519 and circl keys supported

I generated keys using the CIRCL library, but I received an error saying they are not supported. Do I need to make any changes to the code?

Even when I manually execute the generate_cert.go file with the specified flags, I encounter the same error message mentioned above.

Implement HPKE in CIRCL

ECH requires HPKE. Currently the implementation that will be used is githbub.com/cisco/go-hpke (see #30), which in turn depends on github.com/cloudflare/circl for PQ KEMs. Let's add HPKE to circl to close this loop. For now we will only need (X25519, HKDF-SHA256, AES128-GCM).

Refactor golang tests using openssl

The TLS reference tests run a connection against a reference implementation: OpenSSL of TLS and record the bytes of the resulting connection. The command is basically:

bin/go test -v ./src/crypto/tls/... -update

It needs openssl version 1.1, which is sometimes checked by using the checkOpenSSLVersion func.
As that function explains, in order to run the tests, it is needed to install openssl from source and configure it with enable-weak-ssl-ciphers option. It is also needed to install it somewhere that is not replacing the Openssl that comes with the OS, as this can create problems for other applications using openssl: openssl/openssl#9268, so you will want to change the prefix and --openssldir flags accordingly.

On some architectures, it seems that is also needed to configure it with no-shared option, as seen here: https://github.com/thomwiggers/go-1/commit/7c8eefb03cda32c7987b31357d22a8d5d39b5d71 .

Running the -update on the tests sometimes makes them hang or sometimes the code is unable to find the openssl command.

After some examination, it seems that the test that specifically needs all of this is: 5781fef for the deprecated RSA-RC4.

Perhaps, we can do better than this by having a formula or a place to get openssl1.1 correctly configured to run the command. Perhaps, we only need that for the RSA-RC4 case.

Rebase cf on go1.16

Tasks:

  1. [DONE] Update CIRCL once this: cloudflare/circl#215
  2. [DONE] Remove "DO NOT MERGE" commits
  3. [DONE] Squash redundant commits in the "cf" branch
  4. [DONE] Rebase and merge "cf-delegated-crdentials"
  5. [DONE] Rebase "cf" on "cf1.16".

Packages instead of entire Go fork

Would it be possible to break down this repo into the packages necessary/modified?

i.e. such that one could: import "github.com/cloudflare/go-aes-gcm" as a drop-in for the aes package that's builtin.

This would most likely also resolve the issue of moving to go 1.5 .

Unknown field CFEventHandler

I am relatively new to this, so I'm not quite sure why the following doesn't work:

Referring to this article Experiment with post-quantum cryptography today
I wanted to try out the following example code:

package main

import (
  "crypto/tls"
  "fmt"
  "net/http"
)

func main() {
  http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
    CurvePreferences: []tls.CurveID{tls.X25519Kyber512Draft00, tls.X25519},
    CFEventHandler: func(ev tls.CFEvent) {
      switch e := ev.(type) {
      case tls.CFEventTLS13HRR:
        fmt.Printf("HelloRetryRequest\n")
      case tls.CFEventTLS13NegotiatedKEX:
        switch e.KEX {
        case tls.X25519Kyber512Draft00:
          fmt.Printf("Used X25519Kyber512Draft00\n")
        default:
          fmt.Printf("Used %d\n", e.KEX)
        }
      }
    },
  }

  if _, err := http.Get("https://pq.cloudflareresearch.com"); err != nil {
    fmt.Println(err)
  }
}

After I compiled this fork as referenced, I still get this message:

unknown field CFEventHandler in struct literal of type tls.Config

Have there been any changes to the fork since the article was published that would make the referenced example code no longer work?

How to properly deploy ECH in transparent proxy mode

I have a TLS transparent proxy which works like this:

Client ==|TLS request|==> Proxy ==|HTTP Connect|==> Target 

I use https://github.com/inconshreveable/go-vhost to sniff SNI and construct the HTTP Connect request to the target site.

Now I want to add ECH support to my transparent proxy. But I stuck after getting the inner SNI:

tlsConn, _ := vhost.TLS(conn)
sconn := tls.Server(tlsConn, &tls.Config{
    ECHEnabled: true,
    ServerECHProvider: echProvider,
    Certificates: []tls.Certificate{cert},
})
sconn.Handshake()
sconn.ConnectionState().Servername // This is the inner SNI

IIUC, the proxy must tell the client to construct the new inner ClientHello, how can I archive that with the current crypto/tls API?

cc @cjpatton

Copyright for new files

We have added several new files, not all of which are intended to be upstreamed:

  1. src/circl/* -- not intended for upstream
  2. crypto/tls/ech*.go -- not intended for upstream (at least not before RFC)
  3. crypto/tls/delegated_credentials*.go (#28) -- not intended for upstream (at least not before RFC)
  4. crypto/tls/tls_cf.go -- not intended for upstream

The question is how to write copyright information for these files. Things intended for upstream should probably be "Go authors", while things not intended for upstream should be "Cloudflare".

exhaustive checks on DC tests

In TestDCHandshakeServerAuth, the external loop iterates over the dcTests, and the internal loops over the signatureSchemes. It seems that the test is not executing all the combinations of (dcTests, signatureSchemes), is this the intended test?
Inspecting the dcCounter value, it runs from 0 to Len only for the first test case.

	for i, test := range dcTests {
		clientConfig.SupportDelegatedCredential = test.clientDCSupport
+		t.Logf("dcCounter: %v\n", dcCounter)
		for dcCounter < len(dcTestDCScheme)-1 {
			if test.serverDCSupport {
				serverConfig.GetDelegatedCredential = testGetDelegatedCredential
				dcCounter++
			} else {
				serverConfig.GetDelegatedCredential = nil
			}

Creating a ECH client connection

I am trying to create an ECH connection as a client and I was hoping to use this fork in a proof of concept example.

Looking through the source it looks like if I specify ECHEnabled: true in my TLS config without specifying an ECHConfig it will fail over to GREASE.
I am missing on what value/how to create my own ECHConfig struct to pass that in so that I can get a legitimate ECH connection

Performing a dig -t TYPE65 crypto.cloudflare.com request provides me the following and I am assuming ech=<value> is the config I need?

crypto.cloudflare.com.  198     IN      HTTPS   1 . alpn="http/1.1,h2" ipv4hint=162.159.137.85,162.159.138.85 ech=AEb+DQBClAAgACCA88XUXJSY8yxlp6HWzE6uW3fyWQRcLW1e8o48eVAIfQAEAAEAAQATY2xvdWRmbGFyZS1lc25pLmNvbQAA ipv6hint=2606:4700:7::a29f:8955,2606:4700:7::a29f:8a55

I see you guys have an ECHConfig struct in tls/ech_config.go and clearly the tls config options take an array for that is there a marshaling function that I should be using with the raw value that comes back from the DNS lookup?

Also how then would I go about modifying the ClientHelloInner to point to the remote resource I am trying to access.

Sorry for the potentially naive questions, I've been reading over the source and trying to piece things together but I figured I might have better luck asking.

As an example of what I have so far in a toy example. I am fairly certain this is a successful GREASE request?

func main() {
    req, _ := http.NewRequest("GET", "https://crypto.cloudflare.com/cdn-cgi/trace", nil)

    req.Host =  "crypto.cloudflare.com"
    req.Header.Set("User-Agent", "Mozilla/5.0")



    client := http.Client{
        Transport: &http.Transport{
        TLSClientConfig: &tls.Config{
            ServerName:         "crypto.cloudflare.com",
            ECHEnabled:         true,
            },
        },
    }

    o, err:= client.Do(req)

    /* Print response */
    if nil != err {
        log.Fatalf("Dump: %v", err)
    }
    bodyBytes, _ := io.ReadAll(o.Body)
    fmt.Printf("%s\n", string(bodyBytes))
}

Thanks again for your time and work on this!

Improve CIRCL upgrade procedure

One of the main differences between cfgo (there I said) and upstream go is that our fork includes CIRCL in the standard library. To updated CIRCL, we run a script called cf-update-circl.py that:

  1. clones the master branch of github.com/cloudflare/circl;
  2. copies its contents into src/circl;
  3. prunes non-package files and directories (e.g., .git, ASM generators, etc.); and
  4. fixes imports (github.com/cloudflare/circl/kem -> circl/kem and so on, golang.org/x/sys/cpu to internal/cpu).

This process has three problems that I can see:

  1. The script requires occasional maintenance, as changes to upstream CIRCL can break the build. This is inevitable, of course, but CIRCL is currently changing much more quickly than cfgo's requirements for CIRCL change. Instead of copying-then-pruning, we want to make sure that we only build the dependencies we need.
  2. Import fix-ups are done by a simple search-and-replace, which is a bit icky because, in theory, it could change the code.
  3. AFAICT there's no provenance of which version of CIRCL is running. This would be useful for debugging purposes.

There are two ways we can try to remedy this. The first (PR #40) is to use go modules to vendor CIRCL properly. This works pretty well, except that resolving dependencies shared by the standard library and CIRCL requires changing the standard library's dependencies. As we don't know what the side effects of these changes might be, we ought to consider these changes as "unsafe" in general.

With that option off the table, our best option is to improve the existing script. That work is tracked by PR #42.

Plaintext SNI with ECH enabled

I found there is still a plaintext SNI extension cloudflare-esni.com in Clienthello with ECH enabled when connecting to crypto.cloudflare.com with tls.Dial.

tlsConn.ConnectionState().ECHAccepted is true and https://crypto.cloudflare.com/cdn-cgi/trace shows sni=encrypted

Shouldn't there be no SNI in outer Clienthello?

Upstream Proposal

Have these changes been submitted upstream? If not can we get an ETA? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.