Coder Social home page Coder Social logo

cloudflare / tls-tris Goto Github PK

View Code? Open in Web Editor NEW
285.0 21.0 53.0 135.11 MB

crypto/tls, now with 100% more 1.3. THE API IS NOT STABLE AND DOCUMENTATION IS NOT GUARANTEED.

License: Other

Go 94.84% Makefile 1.27% Shell 0.71% Python 2.19% Dockerfile 1.00%

tls-tris's Introduction

 _____ _     ____        _        _
|_   _| |   / ___|      | |_ _ __(_)___
  | | | |   \___ \ _____| __| '__| / __|
  | | | |___ ___) |_____| |_| |  | \__ \
  |_| |_____|____/       \__|_|  |_|___/

crypto/tls, now with 100% more 1.3.

THE API IS NOT STABLE AND DOCUMENTATION IS NOT GUARANTEED.

Build Status

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 1.10 compiler with the required backports.

Development

Dependencies

Copy paste line bellow to install all required dependencies:

  • ArchLinux:
pacman -S go docker gcc git make patch python2 python-docker rsync
  • Debian:
apt-get install build-essential docker go patch python python-pip rsync
pip install setuptools
pip install docker
  • Ubuntu (18.04) :
apt-get update
apt-get install build-essential docker docker.io golang patch python python-pip rsync sudo
pip install setuptools
pip install docker
sudo usermod -a -G docker $USER

Similar dependencies can be found on any UNIX based system/distribution.

Building

There are number of things that need to be setup before running tests. Most important step is to copy go env GOROOT directory to _dev and swap TLS implementation and recompile GO. Then for testing we use go implementation from _dev/GOROOT.

git clone https://github.com/cloudflare/tls-tris.git
cd tls-tris; cp _dev/utils/pre-commit .git/hooks/ 
make -f _dev/Makefile build-all

Testing

We run 3 kinds of test:.

  • Unit testing:
    make -f _dev/Makefile test-unit
  • Testing against BoringSSL test suite:
    make -f _dev/Makefile test-bogo
  • Compatibility testing (see below):
    make -f _dev/Makefile test-interop

To run all the tests in one go use:

make -f _dev/Makefile test

Testing interoperability with 3rd party libraries

In order to ensure compatibility we are testing our implementation against BoringSSL, NSS and PicoTLS.

Makefile has a specific target for testing interoperability with external libraries. Following command can be used in order to run such test:

make -f _dev/Makefile test-interop

The makefile target is just a wrapper and it executes _dev/interop_test_runner script written in python. The script implements interoperability tests using python unittest framework.

Script can be started from command line directly. For example:

> ./interop_test_runner -v InteropServer_NSS.test_zero_rtt
test_zero_rtt (__main__.InteropServer_NSS) ... ok

----------------------------------------------------------------------
Ran 1 test in 8.765s

OK

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. If the value is short, only the error and the first meaningful stack frame are printed.

tls-tris's People

Contributors

agl avatar ality avatar benburkert avatar bradfitz avatar bren2010 avatar cixtor avatar cjpatton avatar davidben avatar filosottile avatar griesemer avatar joneskoo avatar josharian avatar kcons avatar kevinburke avatar kriskwiatkowski avatar lekensteyn avatar marten-seemann avatar minux avatar mkrautz avatar neuromncr avatar nhooyr avatar ralphcorderoy avatar rhencke avatar robpike avatar rsc avatar stemar94 avatar tamird avatar titanous avatar tmthrgd avatar tombergan 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

tls-tris's Issues

Clients MUST check for supported_versions extensions and abort in case it was received on TLS version prior to 1.3

Current code

handshake_messages.go:
...
	svData := findExtension(data, extensionSupportedVersions)
	if svData != nil {
		if len(svData) != 2 {
			return alertDecodeError
		}
		if m.vers != VersionTLS12 {
			return alertDecodeError
		}
		m.vers = uint16(svData[0])<<8 | uint16(svData[1])
	}

As per 4.2.1, if svData is < 0x0304, client MUST abort with illegal_parameter (as server has negotiated TLS 1.2 or older, in which case it MUST NOT send back supportedVersions extension)

draft-25: Add the header to additional data

TLS 1.3, draft-28 specifies AD as record header, i.e.

additional_data = TLSCiphertext.opaque_type 
                            TLSCiphertext.legacy_record_version 
                            TLSCiphertext.length 

This will need to be implemented in tris in order to make it compatible with TLS 1.3

Add SM- ciphersuites

Random thought - I think adding SM2,SM3 and SM4 could be interesting differentiator.

use of internal

Hi,

In your code you use an internal package of an other project : internal/cpu in common.go
Can you fix it please ?

Thanks

Implementation of request_udpate is missing

Draft-22 defines Key and IV Update mechanism. As per point 4.6.3:

If the request_update field is set to "update_requested" then the
   receiver MUST send a KeyUpdate of its own with request_update set to
   "update_not_requested" prior to sending its next application data
   record.

Which means feature is required in order to be fully complient with TLS 1.3 standard

Tests against NSS head do not work anymore

See #66 for more details
Ideally interoperability tests for tls-tris should be done only against hardcoded commit in 3rd party software, which will improve stability and save time spent on debugging.

Actually better solution seems to be not to have interoperability tests and simply use same approach as in handshake_client_test.go and handshake_server_test.go (which is uses data from "testdata" dir). Probably it makes sense to add such improvement after TLSv1.3 spec is finalized

test: Random size messages

It would be useful to have a test which sends random size messages over single TLS 1.3 connection. It doesn't seem such test exists.

Apparent bug in TLS 1.0 (upstream)

When TLS 1.0 is negotiated, Conn.Read() appears to only output 1 byte on the first call, then outputs the remainder of the bytes on the next call. This is not an issue in later versions.

This appears to be an issue with the upstream crypto/tls, and not with tris.

Here's some code for reproducing the bug;

package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"log"
	"net"
)

var certPEM = `-----BEGIN CERTIFICATE-----
MIIBaTCCAQ6gAwIBAgIQSUo+9uaip3qCW+1EPeHZgDAKBggqhkjOPQQDAjASMRAw
DgYDVQQKEwdBY21lIENvMB4XDTE4MDYxMjIzNDAyNloXDTE5MDYxMjIzNDAyNlow
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLf7
fiznPVdc3V5mM3ymswU2/IoJaq/deA6dgdj50ozdYyRiAPjxzcz9zRsZw1apTF/h
yNfiLhV4EE1VrwXcT5OjRjBEMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
BgEFBQcDATAMBgNVHRMBAf8EAjAAMA8GA1UdEQQIMAaHBH8AAAEwCgYIKoZIzj0E
AwIDSQAwRgIhANXG0zmrVtQBK0TNZZoEGMOtSwxmiZzXNe+IjdpxO3TiAiEA5VYx
0CWJq5zqpVXbJMeKVMASo2nrXZoA6NhJvFQ97hw=
-----END CERTIFICATE-----
`

var keyPEM = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMw9DiOfGI1E/XZrrW2huZSjYi0EKwvVjAe+dYtyFsSloAoGCCqGSM49
AwEHoUQDQgAEt/t+LOc9V1zdXmYzfKazBTb8iglqr914Dp2B2PnSjN1jJGIA+PHN
zP3NGxnDVqlMX+HI1+IuFXgQTVWvBdxPkw==
-----END EC PRIVATE KEY-----
`

func main() {
	msg := "hello"

	// Server config
	cert, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM))
	if err != nil {
		log.Fatal(err)
	}
	serverConfig := &tls.Config{
		Certificates: []tls.Certificate{cert},
		MaxVersion:   tls.VersionTLS10,
	}

	// Client config
	rootCAs := x509.NewCertPool()
	root, err := x509.ParseCertificate(
		cert.Certificate[len(cert.Certificate)-1])
	if err != nil {
		log.Fatal(err)
	}
	rootCAs.AddCert(root)
	clientConfig := &tls.Config{
		RootCAs:    rootCAs,
		MaxVersion: tls.VersionTLS10,
	}

	// Create a new listener
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		ln, err = net.Listen("tcp6", "[::1]:0")
	}
	if err != nil {
		log.Fatal(err)
	}
	defer ln.Close()

        // Set up the server socket.
	srvCh := make(chan *tls.Conn, 1)
	var serr error
	go func() {
		sconn, err := ln.Accept()
		if err != nil {
			serr = err
			srvCh <- nil
			return
		}
		srv := tls.Server(sconn, serverConfig)
		if err := srv.Handshake(); err != nil {
			serr = fmt.Errorf("handshake: %v", err)
			srvCh <- nil
			return
		}
		srvCh <- srv
	}()

        // Set up the client socket.
	cli, err := tls.Dial("tcp", ln.Addr().String(), clientConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer cli.Close()

	srv := <-srvCh
	if srv == nil {
		log.Fatal(serr)
	}

	buf := make([]byte, len(msg))
	cli.Write([]byte(msg))

	n := 0
	m, _ := srv.Read(buf)
	// NOTE Uncommenting the following line makes the test pass.
	//n, _ = srv.Read(buf[1:])
	if string(buf[:m+n]) != msg {
		log.Printf("Server read = %d, buf= %q; want %s",
			m+n, buf, msg)
	}
}

Sporadic EOF while reading (interop with NSS)

After adding NSS to the interop tests for #43, the client test sporadically fail (or sporadically succeed ๐Ÿ˜‰ ). The client (_dev/tris-testclient/client.go) is executed against the NSS test server (_dev/tstclnt/server.sh). For some reason it only happens with the TLS 1.2 test, the three following TLS 1.3 tests have no issue. I have not seen the issue with boringssl before.

While trying to track this down, the following message is visible in the travis logs (the "Failed handshakes" line is out of order due to stdout vs stderr, from this build):

+docker run --rm tris-testclient -ecdsa=false 172.17.0.3:1443
TLS 1.2 with TLS_RSA_WITH_AES_128_CBC_SHA
Read failed: EOF

TLS 1.3 with TLS_CHACHA20_POLY1305_SHA256
Read 154 bytes
OK

TLS 1.3 with TLS_AES_128_GCM_SHA256
Read 154 bytes
OK

TLS 1.3 with TLS_AES_256_GCM_SHA384
2017/12/05 14:40:29 Failed handshakes: 1
Read 154 bytes
OK

In another build with pcap+keylog enabled (original log: log-005.txt, commit a8d4e4d, branch pwu/travis), it failed in the second run:

+docker run --rm tris-testclient -rsa=false 172.17.0.3:2443
TLS 1.2 with TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Read failed: EOF

TLS 1.3 with TLS_CHACHA20_POLY1305_SHA256
Read 154 bytes
OK

TLS 1.3 with TLS_AES_128_GCM_SHA256
Read 154 bytes
OK

TLS 1.3 with TLS_AES_256_GCM_SHA384
2017/12/05 14:49:17 Failed handshakes: 1
Read 154 bytes
OK

++echo ERR: 1

In tcp.stream==4 of 005.tar.gz, the server sends application data, close_notify and TCP FIN. The client also sends a close_notify but receives a TCP RST. (In stream 0 where the test passes, the client is earlier with sending its close_notify and FIN/ACK and the server (selfserv) receives a TCP RST instead.)

Restarting this build has these results:

Possibly related issue with the same cause: golang/go#19874


Actually the minimum reproducer seems to be the program below.

mkdir certdb
certutil -d certdb -N --empty-password
certutil -d certdb -S -n rsa-server -t u -x -s CN=localhost -k rsa -z /dev/null
selfserv -n rsa-server   -p 1443 -d certdb -V tls1.2:tls1.3 -v -Z
go run main.go

Output using upstream go version go1.9.2 darwin/amd64 (most of the time this fails the first handshake, but sometimes it fails the second):

2017/12/05 16:05:18 Read 154 bytes
2017/12/05 16:05:18 Read failed: EOF

2017/12/05 16:05:18 Failed handshake: 1
exit status 1

Changing the read buffer size to something smaller (e.g. "1") seems to avoid the issue. Perhaps it should not return EOF when some data is already read (i.e. a partial read).

main.go:

package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
)

func poke(addr string, keylog io.Writer) error {
	tls_config := &tls.Config{
		InsecureSkipVerify: true,
		MinVersion:         tls.VersionTLS12,
		MaxVersion:         tls.VersionTLS12,
		KeyLogWriter:       keylog,
	}
	con, err := tls.Dial("tcp", addr, tls_config)
	if err != nil {
		log.Printf("handshake failed: %v\n\n", err)
		return err
	}
	defer con.Close()

	_, err = con.Write([]byte("GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"))
	if err != nil {
		log.Printf("Write failed: %v\n\n", err)
		return err
	}

	buf := make([]byte, 1024)
	n, err := con.Read(buf)
	if err != nil {
		log.Printf("Read failed: %v\n\n", err)
		return err
	}
	log.Printf("Read %d bytes\n", n)
	return nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Printf("Usage: %s host[:port]\nDefaults to port 443\n", os.Args[0])
		os.Exit(1)
	}
	addr := os.Args[1]
	if !strings.Contains(addr, ":") {
		addr += ":443"
	}

	var keylog io.Writer
	if keylog_file := os.Getenv("SSLKEYLOGFILE"); keylog_file != "" {
		var err error
		keylog, err = os.OpenFile(keylog_file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
		if err != nil {
			log.Fatalf("Cannot open keylog file: %v", err)
		}
		log.Println("Enabled keylog")
	}

	for i := 0; i < 100; i++ {
		if err := poke(addr, keylog); err != nil {
			log.Fatalf("Failed handshake: %d\n", i)
		}
	}

	log.Println("All handshakes passed")
}

TLS-13-Draft-23 plan?

Since draft-23 support is rolled out by chrome 65, Is there any plan for tls-tris draft-23 plan?

Thanks!

document what the Committer is supposed to do (or remove it)

Committer is an interface that the Conn is type asserted against in

tls-tris/13.go

Lines 155 to 159 in e20b4d2

if committer, ok := c.conn.(Committer); ok {
if err := committer.Commit(); err != nil {
return err
}
}

There's no explanation what the purpose of this is, and also the definition of the interface in
type Committer interface {
Commit() error
}
doesn't provide any clues.

Since this is a public interface tris exposes, it should either be properly documented, or removed.

Enable TLS 1.3 by default

Currently TLS 1.2 is used by default. Internally we need to have TLS 1.3 - we will set default version to the TLS 1.3 draft 22

Wrong alert sent by client in case server sends unexpected protocol version in SH.

As per 4.2.1 of TLS 1.3, client needs to verify that TLS version sent by server in the ServerHello is one of those advertised by client.

This is done in:

clientHandshakeState::handshake()
-> pickTLSVersion()

Nevertheless, if server sends unexpected version number client aborts the connection with alertProtocolVersion.

The spec for TLS 1.3 says that client should abort with alertIllegalParameter(47). Which is a bug.
Fixing the problem causes regression in bogo tests, code is not specific to protocol version being negotiated and TLS 1.2 doesn't explicitly specify which alert should be sent in similar case.

Caddy-tris: ERR_SSL_VERSION_INTERFERENCE

I've built caddy with the tris crypto library of go and thus tried out to use tls1.3 with caddy.

I added/modified three lines to the caddytls/config.go: "TLS1-3": TLS_CHACHA20_POLY1305_SHA256 as an additional cipher and to only use this one for TLS1.3 negotiation and "tls1.3": tls.VersionTLS13 for the available TLS versions.

Additionally I stated in the same file, that the max version is tls1.3:

if config.ProtocolMaxVersion == 0 {
                config.ProtocolMaxVersion = tls.VersionTLS13
        }

But still dev.ssllabs.com/ssltest says, that my server negotiates TLS1.3 with a blacklisted HTTP/2 ciphersuite, which is why probably chrome throws the error mentioned in the title.

Any ideas?

Update Caddy.Patch

At line 42, it says: var supportedCiphers = []uint16{

and CHACHA20 Ciphersuites are added to the block in the patch file under: _dev/caddy. But in caddy, this block is no longer present.

So please update this.

Implementation of signature_algorithms_cert

Currently signature_algorithms_cert is implemented in a way that it's sent in a CH and CR, but never parsed when received. We use this extension in order to indicate that certificates with PSS padding are not supported (see #69 (comment)). This support has been added in (golang/go@8786750) which will be released in go 1.11.

  • The parsing part will require some changes in a implementation responsible for certificate dispatching. Server (or client) will need to validate that chosen chain of certificates uses signature algorithms from signature_algorithms_cert list if it's received. There is an exception for root certificate, which needs to be taken into account.
  • Implementation can't change semantics which custom GetCertificate function expects
  • There is a case in which signature_algorithms and signature_algorithms_cert lists share some of the algorithms, but there is also rare corner case in which both lists could be disjoint. Implementation needs to take it into account (verification algorithm of leaf certificate doesn't need to be on a signature_algorithms_cert list)

Comments in this PR are valid only for TLS 1.3

Support for session tickets and other post-handshake messages

In TLS 1.2, the client could not receive NewSessionTicket because it did not advertise the session_ticket extension (RFC 5077). The only post-handshake message it could receive from the server is a HelloRequest message.

In TLS 1.3, the NST message is part of the protocol and does not need an extension. This means that the code must be prepared to accept other post-handshake Handshake messages. In particular:

  • NewSessionTicket
  • KeyUpdate
  • CertificateRequest (only if client advertises post_handshake_auth).

Currently it sends a no_renegotiation alert while it should probably be sending an unexpected_message alert (or handle the message).

Related: golang/go#19199

Client authentication in TLS 1.3

To support client authentication, the server must be extended to send a CertificateRequest message and verify the response (Certificate, CertificateVerify).

The client must be adjusted to process a CertificateRequest message.

Note that post-handshake authentication is out-of-scope for this issue.
Note: draft 19 changes the CertificateRequest format.

Draft -18:

      opaque DistinguishedName<1..2^16-1>;

      struct {
          opaque certificate_extension_oid<1..2^8-1>;
          opaque certificate_extension_values<0..2^16-1>;
      } CertificateExtension;

      struct {
          opaque certificate_request_context<0..2^8-1>;
          SignatureScheme
            supported_signature_algorithms<2..2^16-2>;
          DistinguishedName certificate_authorities<0..2^16-1>;
          CertificateExtension certificate_extensions<0..2^16-1>;
      } CertificateRequest;

Draft -19 to -22:

      struct {
          opaque certificate_request_context<0..2^8-1>;
          Extension extensions<2..2^16-1>;
      } CertificateRequest;

(certificate_authorities got moved to a separate extension, signature_algorithms is a required extension.)

STATUS
Branch https://github.com/cloudflare/tls-tris/commits/pwu/client-auth implements the new CertificateRequest format and wires it up for the client. TODO:

  • implement server side (likely: (1) refactor (extract) TLS 1.2 certificate validation logic (2) wire up TLS 1.3 with this logic)
  • Enable client cert tests in the config.json file, based on FiloSottile/crypto-tls-bogo-shim#2
  • Test and fix bugs.

add a license

Iโ€™d like to use tris in quic-go, but the absence of a license is currently preventing me from doing so.

TLS13-WrongOuterRecord test fails

The TLS13-WrongOuterRecord bogo test expects that clients that receive a handshake content type fail while tris just ignored it.

https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-5.2 says:

opaque_type The outer opaque_type field of a TLSCiphertext record is
always set to the value 23 (application_data) for outward
compatibility with middleboxes accustomed to parsing previous
versions of TLS. The actual content type of the record is found
in TLSInnerPlaintext.type after decryption.

It has no MUST requirement on the receiver, so not sure if we should check it or not.

Fail to negotiate tls13-draft-22 against with chrome 63.

Chrome 63 was shipped with tls13-draft-22 support [1], but seems that current tris cannot co-work with it.

My steps:

  1. build out tris-localserver on commit 8db4726
  2. set chrome://flags/#tls13-variant to Enabled (Experiment)
  3. visit tris-localserver index page.

What I expect:

  • tris-localserver says tls13 works

What I get:

  • tris-localserver says tls12 works.

Meanwhile, the chrome://flags/#tls13-variant option is fine for gmail [2]

[1] https://www.ietf.org/mail-archive/web/tls/current/msg25168.html
[2] https://inbox.google.com

Add nginx TLSv1.3 Patch in "_dev"

Since caddy owns its tls-patch already in this repository, it would be nice to have one for nginx, too, because currently nginx does not support the TLSv1.3 command out of the box and I know there are Dockerpatches for nginx but none for standalone or compiled from source nginx.

Support HelloRetryRequest

Currently the server just closes the connection when no supported groups are available. It should probably send a HRR in this case.

Similarly, the client (PR will be opened "soon") does not expect a HRR, it should retry the CH with appropriate changes (new keyshare for the group).

Important references:
https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.1.4 (Hello Retry Request)
https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.6.1 (PSK Binder)

Note: draft 22 changes the message significantly, requiring different parsing logic.

Support for RSASSA-PSS public keys in certificates

In order to advertise RSASSA-PSS in the supported_algorithms extension, the client (or server in case of mutual auth) must support processing of certificates containing a RSASSA-PSS public key. This is at least the case until at least draft -21.

Currently the server already supports RSASSA-PSS signatures in handshake messages, the client functionality is added in #35 (see that PR for more details).

Support for PSS signatures in TLS 1.2 is proposed here: https://go-review.googlesource.com/q/topic:sigalgs-pss

Key exporters are missing

Point 7.5. in draft-22 defines keying material exporters for TLS. This feature is not implemented in tris

X25519: Check for all zeros value

As per RFC 7748:

   Both now share K = X25519(a, X25519(b, 9)) = X25519(b, X25519(a, 9))
   as a shared secret.  Both MAY check, without leaking extra
   information about the value of K, whether K is the all-zero value and
   abort if so (see below).  Alice and Bob can then use a key-derivation
   function that includes K, K_A, and K_B to derive a symmetric key.

Just to double check if we do that

Abandon interop.sh

In order to improve testability following fixes will be introduced:

  1. interop.sh needs to be abandoned
  2. _dev/Makefile needs to be improved to incorporate what's currently in interop.sh
  3. .travis.yml needs to call make

Validation of unexpected extensions

Currently unexpected extensions are silently ignored, but these must result in a failure. Similarly, duplicate extensions are not checked at the moment.

The following requirements are imposed from https://tools.ietf.org/html/draft-ietf-tls-tls13-18#page-35:

If the client receives an extension which is not specified for a given
message it MUST abort the handshake with an "illegal_parameter"
alert.

Upon receiving an unexpected extension, it MUST abort the handshake
with an "unsupported_extension" alert.

There MUST NOT be more than one extension of the same type.

Addressing these issues will fix a bunch of bogo failures.

Support for draft 22

Current master supports draft 18 only. During the IETF 100 hackathon, partial support was added for "soon-to-be-draft 22" based on the pwu/client branch from #43.

While working on tests for draft22, I have found some issues:

  • bogo: assumes draft18 support, fails for instance the FallbackSCSV-VersionMatch-TLS13 test with "Inappropriate fallback" because our server does not recognize the advertised draft 18 version in supported_versions. Requires https://boringssl-review.googlesource.com/c/boringssl/+/23704 integrated into draft22 branch of shim
  • boringssl: client requires -tls-variant draft22, but that uses an experimental codepoint (7e04) for supported_version instead of 7f18 (presumably since the draft is not final yet). bogo shim is now updated to use the final draft version
  • tstclnt (NSS): fails with "tls: invalid client PSK" tris fix pending, draft 21 added a ticket nonce which changed the PSK calculation
  • picotls client: fails with "ptls_handshake:47" (possibly because we require X25519 while picotls seems to use P256 and sends a HRR which we do not support yet).

Branches:

  • tris: pwu/draft22 - draft22 client+server developed during hackathon
  • tris: pwu/server-draft22 - attempt to integrate draft22 with the server only (since client support is not merged yet)
  • crypto-tls-bogo-shim: https://github.com/FiloSottile/crypto-tls-bogo-shim/tree/draft22 - update with latest bogo code that "supports" draft22 (but with above issue)

Large records are rejected

Currently tris rejects TLSInnerPlaintext (https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-5.2) larger than 2^14 bytes with a Record Overflow alert. At least boringssl server (draft -18) and Firefox 56 send/receive a TLSInnerPlaintext of 2^14+1 (1 for content type, 2^14 for the content) without failing.

Seems to be the result of an ambiguity:
https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-5.4

The presence of padding does not change the overall record size
limitations - the full fragment plaintext may not exceed 2^14 octets.

This was later clarified in draft -20 (tlswg/tls13-spec@f829c818) to:

The presence of padding does not change the overall record size limitations - the full encoded
TLSInnerPlaintext MUST not exceed 2^14 octets.

Originally found with the "LargeMessage" bogo test, later reproduced with tris-testclient against https://tls.ctf.network/

Even the latest draft -21 version of OpenSSL (OpenSSL_1_1_0-pre6-3318-g270a4bba49) still violates this. Tested by connecting s_client to s_server with a large certificate. Wireshark shows that "Decrypted SSL" is 16384 bytes which covers the content field only. In the "SSL debug file" you will see an additional content type byte prepended.
Same for the latest draft -21 version of NSS (76d5048d2b8a 2017-10-01 09:34 +1100), it also creates a large record.

Tests

Create cert+keys (and convert to PKCS#12 form for NSS):

openssl req -newkey rsa:2048 -x509 -nodes -keyout server.pem -new -out server.pem -subj $(for i in {1..2000};do printf /CN=localhost; done)
openssl pkcs12 -export -in server.pem -inkey server.pem -out server.p12 -name testserver -passout pass:testtest
pk12util -i server.p12 -d . -K testtest -W testtest

Tested servers / clients (with keylog so you can actually check the record contents), all of them produce at least one record with 16384+1 bytes:

# affected: OpenSSL_1_1_0-pre6-3318-g270a4bba49 draft-21
openssl s_server
openssl s_client -keylogfile keys -servername $SNI

# affected: NSS_3_27_BETA3-866-c1866d7d7f15 draft-18
selfserv -n testserver -p 4433 -v -d . -w testtest
SSLKEYLOGFILE=keys tstclnt -h 127.0.0.1 -p 4433 -o -d . -a $SNI

# affected: boringssl-e7136a978f6f9d5b3f392b661e573e0793965f97 draft-18
bssl server -key server.pem -accept 4433
SSLKEYLOGFILE=keys bssl client -connect 127.0.0.1:4433 -server-name $SNI

# maybe affected: picotls-a31bf852ad6b98bb5549b4233c08e98258c203bf draft-21
# cli: picotls.c:477: buffer_encrypt_record: Assertion `bodylen <= PTLS_MAX_PLAINTEXT_RECORD_SIZE' failed.
cli -c server.pem -k server.pem localhost 4433
cli -l keys $SNI.localhost 4433

# affected: wolfssl v3.12.0-stable-162-g918a5fd5
# needs https://github.com/Lekensteyn/wolfssl/tree/sslkeylogfile for SSLKEYLOGFILE
examples/server/server -c server.pem -k server.pem -p4433 -v4
SSLKEYLOGFILE=keys examples/client/client -p4433 -v4

Fixing tls-tris history

The previous rebase method was not deterministic, I have described a new one at
https://github.com/cloudflare/tls-tris/wiki/Rebase to ensure that every rebase attempt results in the same tree.

The https://github.com/cloudflare/tls-tris/tree/pwu/master-fixed-history branch reflects the current master, but with fixed up committers information. (The commit history diverged after https://github.com/cloudflare/tls-tris/tree/pwu/go-update/branchpoint). Is it OK to force-push master with this fixed version?

Using the above method, I created these three branches (where the latter branches follow the former ones):
https://github.com/cloudflare/tls-tris/tree/pwu/go-update/go1.7
https://github.com/cloudflare/tls-tris/tree/pwu/go-update/go1.8
https://github.com/cloudflare/tls-tris/tree/pwu/go-update/go1.9
Current master reflects something between 1.7 and 1.8, rebases on 1.8 and 1.9 with fixups are WIP in https://github.com/cloudflare/tls-tris/tree/pwu/master-go1.8-rebase and https://github.com/cloudflare/tls-tris/tree/pwu/master-go1.9-rebase

go test returns an error

When trying to run tests for tls-tris I get an error:

> ./_dev/go.sh test
common.go:10:2: use of internal package not allowed
cipher_suites.go:18:2: cannot find package "golang_org/x/crypto/chacha20poly1305" in any of:
	/home/hdc/repos/cloudflare/tls-tris/_dev/GOROOT/linux_amd64/src/golang_org/x/crypto/chacha20poly1305 (from $GOROOT)
	/home/hdc/go/src/golang_org/x/crypto/chacha20poly1305 (from $GOPATH)
13.go:24:2: cannot find package "golang_org/x/crypto/curve25519" in any of:
	/home/hdc/repos/cloudflare/tls-tris/_dev/GOROOT/linux_amd64/src/golang_org/x/crypto/curve25519 (from $GOROOT)
	/home/hdc/go/src/golang_org/x/crypto/curve25519 (from $GOPATH)
hdc@cryptoden 6:45 ~/repos/cloudflare/tls-tris 

Support for 0-RTT

It was reported that support for 0-RTT has an interoperability issue (tested against OpenSSL and Haskel TLS). We do have tests for 0-RTT, but they may not cover functionality completely .
To be investigated first and fixed

The lack of package

I do build
cipher_suites.go:9:2: cannot find package "crypto/chacha20poly1305" in any of:
/usr/local/go/src/crypto/chacha20poly1305 (from $GOROOT)
~/gopath/src/crypto/chacha20poly1305 (from $GOPATH)

Wrong alert returned when client doesn't provide "signature_algorithms"

Draft of TLS 1.3 says in 4.2.3:

If a server is authenticating via a
   certificate and the client has not sent a "signature_algorithms"
   extension, then the server MUST abort the handshake with a
   "missing_extension" alert (see Section 9.2).

Currently code doesn't send this code as "missing_extension" alert is not even on a list of alerts

Test TestSCTHandshake seems not to work with TLS 1.3

Description

The test TestSCTHandshake requires 2 SignedCertificateTimestamps to be set.

Expected behaviour

The test TestSCTHandshake requires 2 SignedCertificateTimestamps to be set on client's ConnectionState object after handshake is tested with a call to testHandshake().

Current behaviour

Current behviour is as expected if TLS v1.2 (or earlier) is negotiated between parties. Nevertheless, if TLS v1.3 is negotiated SignedCertificateTimestamps list is empty. This is causing following condition to be true and results in broken test

	actual := state.SignedCertificateTimestamps
	if len(actual) != len(expected) {
		t.Fatalf("got %d scts, want %d", len(actual), len(expected))
	}

Is clientHelloMsg13 missing or unimplemented?

This is a brilliant project! Thank you for your works.

I noticed that serverHelloMsg13 was implemented for building a tls1.3 server.
Seems that clientHelloMsg13 missed and it prevented me to create a tls1.3 client.

If my understanding is right, any thoughts about the tls1.3 client ?
Thank you again!

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.