crypto/tls: implement (*ClientHelloInfo).SupportsCertificate

We'll also use this function for a better selection logic from
Config.Certificates in a later CL.

Updates #32426

Change-Id: Ie239574d02eb7fd2cf025ec36721c8c7e082d0bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/205057
Reviewed-by: Katie Hockman <katie@golang.org>
This commit is contained in:
Filippo Valsorda 2019-11-01 19:00:33 -04:00
parent 0c490ab182
commit da96d661d8
3 changed files with 329 additions and 0 deletions

View file

@ -1045,3 +1045,162 @@ func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) {
}
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
func TestClientHelloInfo_SupportsCertificate(t *testing.T) {
rsaCert := &Certificate{
Certificate: [][]byte{testRSACertificate},
PrivateKey: testRSAPrivateKey,
}
ecdsaCert := &Certificate{
// ECDSA P-256 certificate
Certificate: [][]byte{testP256Certificate},
PrivateKey: testP256PrivateKey,
}
ed25519Cert := &Certificate{
Certificate: [][]byte{testEd25519Certificate},
PrivateKey: testEd25519PrivateKey,
}
tests := []struct {
c *Certificate
chi *ClientHelloInfo
wantErr string
}{
{rsaCert, &ClientHelloInfo{
ServerName: "example.golang",
SignatureSchemes: []SignatureScheme{PSSWithSHA256},
SupportedVersions: []uint16{VersionTLS13},
}, ""},
{ecdsaCert, &ClientHelloInfo{
SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS13, VersionTLS12},
}, ""},
{rsaCert, &ClientHelloInfo{
ServerName: "example.com",
SignatureSchemes: []SignatureScheme{PSSWithSHA256},
SupportedVersions: []uint16{VersionTLS13},
}, "not valid for requested server name"},
{ecdsaCert, &ClientHelloInfo{
SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384},
SupportedVersions: []uint16{VersionTLS13},
}, "signature algorithms"},
{rsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
SignatureSchemes: []SignatureScheme{PKCS1WithSHA1},
SupportedVersions: []uint16{VersionTLS13, VersionTLS12},
}, "signature algorithms"},
{rsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
SignatureSchemes: []SignatureScheme{PKCS1WithSHA1},
SupportedVersions: []uint16{VersionTLS13, VersionTLS12},
config: &Config{
MaxVersion: VersionTLS12,
},
}, ""}, // Check that mutual version selection works.
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS12},
}, ""},
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384},
SupportedVersions: []uint16{VersionTLS12},
}, ""}, // TLS 1.2 does not restrict curves based on the SignatureScheme.
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: nil,
SupportedVersions: []uint16{VersionTLS12},
}, ""}, // TLS 1.2 comes with default signature schemes.
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS12},
}, "cipher suite"},
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS12},
config: &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
},
}, "cipher suite"},
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP384},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS12},
}, "certificate curve"},
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{1},
SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256},
SupportedVersions: []uint16{VersionTLS12},
}, "doesn't support ECDHE"},
{ecdsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{PSSWithSHA256},
SupportedVersions: []uint16{VersionTLS12},
}, "signature algorithms"},
{ed25519Cert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{Ed25519},
SupportedVersions: []uint16{VersionTLS12},
}, ""},
{ed25519Cert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{Ed25519},
SupportedVersions: []uint16{VersionTLS10},
}, "doesn't support Ed25519"},
{ed25519Cert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
SupportedCurves: []CurveID{},
SupportedPoints: []uint8{pointFormatUncompressed},
SignatureSchemes: []SignatureScheme{Ed25519},
SupportedVersions: []uint16{VersionTLS12},
}, "doesn't support ECDHE"},
{rsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support
SupportedPoints: []uint8{pointFormatUncompressed},
SupportedVersions: []uint16{VersionTLS10},
}, ""},
{rsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
SupportedVersions: []uint16{VersionTLS12},
}, ""}, // static RSA fallback
}
for i, tt := range tests {
err := tt.chi.SupportsCertificate(tt.c)
switch {
case tt.wantErr == "" && err != nil:
t.Errorf("%d: unexpected error: %v", i, err)
case tt.wantErr != "" && err == nil:
t.Errorf("%d: unexpected success", i)
case tt.wantErr != "" && !strings.Contains(err.Error(), tt.wantErr):
t.Errorf("%d: got error %q, expected %q", i, err, tt.wantErr)
}
}
}