crypto/tls: add support for Certificate Transparency

This change adds support for serving and receiving Signed Certificate
Timestamps as described in RFC 6962.

The server is now capable of serving SCTs listed in the Certificate
structure. The client now asks for SCTs and, if any are received,
they are exposed in the ConnectionState structure.

Fixes #10201

Change-Id: Ib3adae98cb4f173bc85cec04d2bdd3aa0fec70bb
Reviewed-on: https://go-review.googlesource.com/8988
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
Reviewed-by: Jonathan Rudenberg <jonathan@titanous.com>
This commit is contained in:
Jonathan Rudenberg 2015-04-16 14:59:22 -04:00 committed by Adam Langley
parent 2db58f8f2d
commit 02e69c4b53
31 changed files with 1106 additions and 779 deletions

View file

@ -303,19 +303,20 @@ func TestClose(t *testing.T) {
}
}
func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, err error) {
func testHandshake(clientConfig, serverConfig *Config) (serverState, clientState ConnectionState, err error) {
c, s := net.Pipe()
done := make(chan bool)
go func() {
cli := Client(c, clientConfig)
cli.Handshake()
clientState = cli.ConnectionState()
c.Close()
done <- true
}()
server := Server(s, serverConfig)
err = server.Handshake()
if err == nil {
state = server.ConnectionState()
serverState = server.ConnectionState()
}
s.Close()
<-done
@ -330,7 +331,7 @@ func TestVersion(t *testing.T) {
clientConfig := &Config{
InsecureSkipVerify: true,
}
state, err := testHandshake(clientConfig, serverConfig)
state, _, err := testHandshake(clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
@ -349,7 +350,7 @@ func TestCipherSuitePreference(t *testing.T) {
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
InsecureSkipVerify: true,
}
state, err := testHandshake(clientConfig, serverConfig)
state, _, err := testHandshake(clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
@ -359,7 +360,7 @@ func TestCipherSuitePreference(t *testing.T) {
}
serverConfig.PreferServerCipherSuites = true
state, err = testHandshake(clientConfig, serverConfig)
state, _, err = testHandshake(clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
@ -368,6 +369,33 @@ func TestCipherSuitePreference(t *testing.T) {
}
}
func TestSCTHandshake(t *testing.T) {
expected := [][]byte{[]byte("certificate"), []byte("transparency")}
serverConfig := &Config{
Certificates: []Certificate{{
Certificate: [][]byte{testRSACertificate},
PrivateKey: testRSAPrivateKey,
SignedCertificateTimestamps: expected,
}},
}
clientConfig := &Config{
InsecureSkipVerify: true,
}
_, state, err := testHandshake(clientConfig, serverConfig)
if err != nil {
t.Fatalf("handshake failed: %s", err)
}
actual := state.SignedCertificateTimestamps
if len(actual) != len(expected) {
t.Fatalf("got %d scts, want %d", len(actual), len(expected))
}
for i, sct := range expected {
if !bytes.Equal(sct, actual[i]) {
t.Fatalf("SCT #%d was %x, but expected %x", i, actual[i], sct)
}
}
}
// Note: see comment in handshake_test.go for details of how the reference
// tests work.