Use static test data for testing delegated credentials
This removes dependency on NewDelegatedCredential from tris.
This commit is contained in:
parent
22d6deb0e7
commit
1ea9624098
414
subcerts_test.go
414
subcerts_test.go
@ -5,24 +5,15 @@
|
|||||||
package tls
|
package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"errors"
|
"encoding/asn1"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dcWithPrivateKey stores a delegated credential and its corresponding private
|
|
||||||
// key.
|
|
||||||
type dcWithPrivateKey struct {
|
|
||||||
*DelegatedCredential
|
|
||||||
privateKey crypto.PrivateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// These test keys were generated with the following program, available in the
|
// These test keys were generated with the following program, available in the
|
||||||
// crypto/tls directory:
|
// crypto/tls directory:
|
||||||
//
|
//
|
||||||
@ -68,34 +59,80 @@ zP3NGxnDVqlMX+HI1+IuFXgQTVWvBdxPkw==
|
|||||||
-----END EC PRIVATE KEY-----
|
-----END EC PRIVATE KEY-----
|
||||||
`
|
`
|
||||||
|
|
||||||
// Invalid TLS versions used for testing purposes.
|
var dcTestDCsPEM = `-----BEGIN DC TEST DATA-----
|
||||||
const (
|
MIIGQzCCAToTBXRsczEyAgIDAwICBAMEga0ACUp3AFswWTATBgcqhkjOPQIBBggq
|
||||||
versionInvalidDC uint16 = 0xff00
|
hkjOPQMBBwNCAAQ9z9RDrMvyRzPOkw9SK2S/O5DiwfRNjAwYcq7e/sKdN0ZcSP1K
|
||||||
versionMalformedDC12 uint16 = 0xff12
|
se/+ZDXfruwyviuq+h5oSzWPoejHHx7jnwBTBAMASDBGAiEAtYH/x0Ue2B2a34WG
|
||||||
versionMalformedDC13 uint16 = 0xff13
|
Oj9wVPJeyYBXxIbUrCdqfoQzq2oCIQCJYtwRE9UJvAQKve4ulJOr+zGjN8jG4tdg
|
||||||
)
|
9YSb/yOQgQR5MHcCAQEEIOBCmSaGwzZtXOJRCbA03GgxegoSV5GasVjJlttpUAPh
|
||||||
|
oAoGCCqGSM49AwEHoUQDQgAEPc/UQ6zL8kczzpMPUitkvzuQ4sH0TYwMGHKu3v7C
|
||||||
|
nTdGXEj9SrHv/mQ1367sMr4rqvoeaEs1j6Hoxx8e458AUzCCATgTBXRsczEzAgJ/
|
||||||
|
FwICBAMEgasACUp3AFswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARcqxvo0JO1
|
||||||
|
yiXoBhV/T2hmkUhwMnP5XtTJCGGfI0ILShmTeuTcScmiTuzo3qA/HVmr2sdnfBvx
|
||||||
|
zhQOYXrsfTNxBAMARjBEAiB8xrQk3DRFkACXMLZTJ1jAml/2zj/Vqc4cav0xi9zk
|
||||||
|
dQIgDSrNtkK1akKGeNt7Iquv0lLZgyLp1i+rwQwOTdbw6ScEeTB3AgEBBCC7JqZM
|
||||||
|
yIFzXdTmuYIUqOGQ602V4VtQttg/Oh2NuSCteKAKBggqhkjOPQMBB6FEA0IABFyr
|
||||||
|
G+jQk7XKJegGFX9PaGaRSHAyc/le1MkIYZ8jQgtKGZN65NxJyaJO7OjeoD8dWava
|
||||||
|
x2d8G/HOFA5heux9M3EwggE9EwdpbnZhbGlkAgMA/wACAgQDBIGtAAlKdwBbMFkw
|
||||||
|
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdlKK5Dv35nOxaTS0LGqBnQstHSqVFIoZ
|
||||||
|
FsHGdXuR2N4pAoMkUF0w94+BZ/KHm1Djv/ugELm0aMHp8SBbJV3JVQQDAEgwRgIh
|
||||||
|
AL/gfo5JGFV/pNZe4ktc2yO41a4ipFvb8WIv8qn29gjoAiEAw1DB1EelNEfjl+fp
|
||||||
|
CDMT+mdFKRDMnXTRrM2K8gI1QsEEeTB3AgEBBCCdu3sMkUAsbHAcYOZ9wJnQujWr
|
||||||
|
5UqPQotIys9hqJ3PTaAKBggqhkjOPQMBB6FEA0IABHZSiuQ79+ZzsWk0tCxqgZ0L
|
||||||
|
LR0qlRSKGRbBxnV7kdjeKQKDJFBdMPePgWfyh5tQ47/7oBC5tGjB6fEgWyVdyVUw
|
||||||
|
ggFAEwttYWxmb3JtZWQxMgICAwMCAgQDBIGtAAlKdwBbMFkwEwYHKoZIzj0CAQYI
|
||||||
|
KoZIzj0DAQcDQgAEn8Rr7eedTHuGJjv7mglv7nJrV7KMDE2A33v8EAMGU+AvRq2m
|
||||||
|
XNIoc+a6JxpYetjTnT3s8TW4qWXq9dJzw3VAVgQDAEgwRgIhAKEVbifQNllzjTwX
|
||||||
|
s5CUsN42Eo8R8WTiFNSbhJmqDKsCAiEA4cqhQA2Cop2WtuOAG3aMnO9MKAPxLeUc
|
||||||
|
fEmnM658P3kEeTB3AgEBBCAR4EtE/WbJIc6id2bLOR4xgis7mzOWJdiRAiGKNshB
|
||||||
|
iKAKBggqhkjOPQMBB6FEA0IABF/2VNK9W/QsMdiBn3qdG19trNMAFvVM0JbeBHin
|
||||||
|
gl/7WVXGBk0WzgvmA0qSH4Bc7d8z8n3JKdmByYPgpxTjbFUwggFAEwttYWxmb3Jt
|
||||||
|
ZWQxMwICAwQCAgQDBIGtAAlKdwBbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
|
||||||
|
FGWBYWhjdr9al2imEFlGx+r0tQdcEqL/Qtf7imo/z5fr2z+tG3TawC0QeHU6uyRX
|
||||||
|
8zPvZGJ/Xps5q3RBI0tVggQDAEgwRgIhAMv30xlPKpajZuahNRHx3AlGtM9mNt5K
|
||||||
|
WbWvhqDXhlVgAiEAxqI0K57Y9p9lLC8cSoy2arppjPMWKkVA4G2ck2n4NwUEeTB3
|
||||||
|
AgEBBCCaruxlln2bwAX0EGy4oge0EpSDObt8Z+pNqx1nxDYyYKAKBggqhkjOPQMB
|
||||||
|
B6FEA0IABBYfBBlgDC3TLkbJJTTJaZMXiXvDkUiWMeYFpcbAHdvMI8zoS6b++Zgc
|
||||||
|
HJbn52hmB027JEIMPWsxKxPkr7udk7Q=
|
||||||
|
-----END DC TEST DATA-----
|
||||||
|
`
|
||||||
|
|
||||||
var dcTestConfig *Config
|
type dcTestDC struct {
|
||||||
var dcTestCerts map[string]*Certificate
|
Name string
|
||||||
var dcTestDCs map[uint16]dcWithPrivateKey
|
Version int
|
||||||
var dcNow time.Time
|
Scheme int
|
||||||
var dcTestDCScheme = ECDSAWithP521AndSHA512
|
DC []byte
|
||||||
var dcTestDCVersions = []uint16{
|
PrivateKey []byte
|
||||||
VersionTLS12,
|
|
||||||
VersionTLS13,
|
|
||||||
VersionTLS13Draft23,
|
|
||||||
versionInvalidDC,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dcTestDCs []dcTestDC
|
||||||
|
var dcTestConfig *Config
|
||||||
|
var dcTestDelegationCert Certificate
|
||||||
|
var dcTestCert Certificate
|
||||||
|
var dcTestNow time.Time
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
// Use a static time for testing at whcih time the test certificates are
|
// Parse the PEM-encoded DER block containing the test DCs.
|
||||||
// valid.
|
block, _ := pem.Decode([]byte(dcTestDCsPEM))
|
||||||
dcNow = time.Date(2018, 07, 03, 18, 0, 0, 234234, time.UTC)
|
if block == nil {
|
||||||
|
panic("failed to decode DC tests PEM block")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the DER-encoded test DCs.
|
||||||
|
_, err := asn1.Unmarshal(block.Bytes, &dcTestDCs)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to unmarshal DC test ASN.1 data")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a static time for testing. This is the point at which the test DCs
|
||||||
|
// were generated.
|
||||||
|
dcTestNow = time.Date(2018, 07, 03, 18, 0, 0, 234234, time.UTC)
|
||||||
|
|
||||||
|
// The base configuration for the client and server.
|
||||||
dcTestConfig = &Config{
|
dcTestConfig = &Config{
|
||||||
Time: func() time.Time {
|
Time: func() time.Time {
|
||||||
return dcNow
|
return dcTestNow
|
||||||
},
|
},
|
||||||
Rand: zeroSource{},
|
Rand: zeroSource{},
|
||||||
Certificates: nil,
|
Certificates: nil,
|
||||||
@ -104,230 +141,51 @@ func init() {
|
|||||||
CipherSuites: allCipherSuites(),
|
CipherSuites: allCipherSuites(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The certificates of the server.
|
|
||||||
dcTestCerts = make(map[string]*Certificate)
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// The delegation certificate.
|
// The delegation certificate.
|
||||||
dcCert := new(Certificate)
|
dcTestDelegationCert, err = X509KeyPair([]byte(delegatorCertPEM), []byte(delegatorKeyPEM))
|
||||||
*dcCert, err = X509KeyPair([]byte(delegatorCertPEM), []byte(delegatorKeyPEM))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dcCert.Leaf, err = x509.ParseCertificate(dcCert.Certificate[0])
|
dcTestDelegationCert.Leaf, err = x509.ParseCertificate(dcTestDelegationCert.Certificate[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dcTestCerts["dc"] = dcCert
|
|
||||||
|
|
||||||
// The standard certificate.
|
// A certificate without the the DelegationUsage extension for X.509.
|
||||||
ndcCert := new(Certificate)
|
dcTestCert, err = X509KeyPair([]byte(nonDelegatorCertPEM), []byte(nonDelegatorKeyPEM))
|
||||||
*ndcCert, err = X509KeyPair([]byte(nonDelegatorCertPEM), []byte(nonDelegatorKeyPEM))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
ndcCert.Leaf, err = x509.ParseCertificate(ndcCert.Certificate[0])
|
dcTestCert.Leaf, err = x509.ParseCertificate(dcTestCert.Certificate[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dcTestCerts["no dc"] = ndcCert
|
|
||||||
|
|
||||||
// The root certificates for the client.
|
// Make these roots of these certificates the client's trusted CAs.
|
||||||
dcTestConfig.RootCAs = x509.NewCertPool()
|
dcTestConfig.RootCAs = x509.NewCertPool()
|
||||||
|
|
||||||
dcRoot, err := x509.ParseCertificate(dcCert.Certificate[len(dcCert.Certificate)-1])
|
raw := dcTestDelegationCert.Certificate[len(dcTestDelegationCert.Certificate)-1]
|
||||||
|
root, err := x509.ParseCertificate(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dcTestConfig.RootCAs.AddCert(dcRoot)
|
dcTestConfig.RootCAs.AddCert(root)
|
||||||
|
|
||||||
ndcRoot, err := x509.ParseCertificate(ndcCert.Certificate[len(ndcCert.Certificate)-1])
|
raw = dcTestCert.Certificate[len(dcTestCert.Certificate)-1]
|
||||||
|
root, err = x509.ParseCertificate(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dcTestConfig.RootCAs.AddCert(ndcRoot)
|
dcTestConfig.RootCAs.AddCert(root)
|
||||||
|
|
||||||
// A pool of DCs.
|
|
||||||
dcTestDCs = make(map[uint16]dcWithPrivateKey)
|
|
||||||
for _, vers := range dcTestDCVersions {
|
|
||||||
dc, sk, err := NewDelegatedCredential(dcCert, dcTestDCScheme, dcNow.Sub(dcCert.Leaf.NotBefore)+dcMaxTTL, vers)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
dcTestDCs[vers] = dcWithPrivateKey{dc, sk}
|
|
||||||
}
|
|
||||||
// Add two DCs with invalid private keys, one for TLS 1.2 and another for
|
|
||||||
// 1.3.
|
|
||||||
malformedDC12 := new(DelegatedCredential)
|
|
||||||
*malformedDC12 = *dcTestDCs[VersionTLS12].DelegatedCredential
|
|
||||||
dcTestDCs[versionMalformedDC12] = dcWithPrivateKey{
|
|
||||||
malformedDC12,
|
|
||||||
dcTestDCs[versionInvalidDC].privateKey,
|
|
||||||
}
|
|
||||||
malformedDC13 := new(DelegatedCredential)
|
|
||||||
*malformedDC13 = *dcTestDCs[VersionTLS13].DelegatedCredential
|
|
||||||
dcTestDCs[versionMalformedDC13] = dcWithPrivateKey{
|
|
||||||
malformedDC13,
|
|
||||||
dcTestDCs[versionInvalidDC].privateKey,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkECDSAPublicKeysEqual(
|
|
||||||
publicKey, publicKey2 crypto.PublicKey, scheme SignatureScheme) error {
|
|
||||||
|
|
||||||
curve := getCurve(scheme)
|
|
||||||
pk := publicKey.(*ecdsa.PublicKey)
|
|
||||||
pk2 := publicKey2.(*ecdsa.PublicKey)
|
|
||||||
serializedPublicKey := elliptic.Marshal(curve, pk.X, pk.Y)
|
|
||||||
serializedPublicKey2 := elliptic.Marshal(curve, pk2.X, pk2.Y)
|
|
||||||
if !bytes.Equal(serializedPublicKey2, serializedPublicKey) {
|
|
||||||
return errors.New("PublicKey mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that cred and cred2 are equal.
|
|
||||||
func checkCredentialsEqual(dc, dc2 *DelegatedCredential) error {
|
|
||||||
if dc2.ValidTime != dc.ValidTime {
|
|
||||||
return fmt.Errorf("ValidTime mismatch: got %d; want %d", dc2.ValidTime, dc.ValidTime)
|
|
||||||
}
|
|
||||||
if dc2.publicKeyScheme != dc.publicKeyScheme {
|
|
||||||
return fmt.Errorf("scheme mismatch: got %04x; want %04x", dc2.publicKeyScheme, dc.publicKeyScheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkECDSAPublicKeysEqual(dc.PublicKey, dc2.PublicKey, dc.publicKeyScheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test delegation and validation of credentials.
|
|
||||||
func TestDelegateValidate(t *testing.T) {
|
|
||||||
ver := uint16(VersionTLS12)
|
|
||||||
cert := dcTestCerts["dc"]
|
|
||||||
|
|
||||||
validTime := dcNow.Sub(cert.Leaf.NotBefore) + dcMaxTTL
|
|
||||||
shortValidTime := dcNow.Sub(cert.Leaf.NotBefore) + time.Second
|
|
||||||
|
|
||||||
delegatedCred, _, err := NewDelegatedCredential(cert, ECDSAWithP256AndSHA256, validTime, ver)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test validation of good DC.
|
|
||||||
if v, err := delegatedCred.Validate(cert.Leaf, ver, dcNow); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
} else if !v {
|
|
||||||
t.Error("good DC is invalid; want valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test validation of expired DC.
|
|
||||||
tooLate := dcNow.Add(dcMaxTTL).Add(time.Nanosecond)
|
|
||||||
if v, err := delegatedCred.Validate(cert.Leaf, ver, tooLate); err == nil {
|
|
||||||
t.Error("expired DC validation succeeded; want failure")
|
|
||||||
} else if v {
|
|
||||||
t.Error("expired DC is valid; want invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test protocol binding.
|
|
||||||
if v, err := delegatedCred.Validate(cert.Leaf, VersionSSL30, dcNow); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if v {
|
|
||||||
t.Error("DC with wrong version is valid; want invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test signature algorithm binding.
|
|
||||||
delegatedCred.Scheme = ECDSAWithP521AndSHA512
|
|
||||||
if v, err := delegatedCred.Validate(cert.Leaf, ver, dcNow); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if v {
|
|
||||||
t.Error("DC with wrong scheme is valid; want invalid")
|
|
||||||
}
|
|
||||||
delegatedCred.Scheme = ECDSAWithP256AndSHA256
|
|
||||||
|
|
||||||
// Test delegation cedrtificate binding.
|
|
||||||
cert.Leaf.Raw[0] ^= byte(42)
|
|
||||||
if v, err := delegatedCred.Validate(cert.Leaf, ver, dcNow); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if v {
|
|
||||||
t.Error("DC with wrong cert is valid; want invalid")
|
|
||||||
}
|
|
||||||
cert.Leaf.Raw[0] ^= byte(42)
|
|
||||||
|
|
||||||
// Test validation of DC who's TTL is too long.
|
|
||||||
delegatedCred2, _, err := NewDelegatedCredential(cert, ECDSAWithP256AndSHA256, validTime+time.Second, ver)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if v, err := delegatedCred2.Validate(cert.Leaf, ver, dcNow); err == nil {
|
|
||||||
t.Error("DC validation with long TTL succeeded; want failure")
|
|
||||||
} else if v {
|
|
||||||
t.Error("DC with long TTL is valid; want invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test validation of DC who's TTL is short.
|
|
||||||
delegatedCred3, _, err := NewDelegatedCredential(cert, ECDSAWithP256AndSHA256, shortValidTime, ver)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if v, err := delegatedCred3.Validate(cert.Leaf, ver, dcNow); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
} else if !v {
|
|
||||||
t.Error("good DC is invalid; want valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test validation of DC using a certificate that can't delegate.
|
|
||||||
if v, err := delegatedCred.Validate(
|
|
||||||
dcTestCerts["no dc"].Leaf, ver, dcNow); err != errNoDelegationUsage {
|
|
||||||
t.Error("DC validation with non-delegation cert succeeded; want failure")
|
|
||||||
} else if v {
|
|
||||||
t.Error("DC with non-delegation cert is valid; want invalid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test encoding/decoding of delegated credentials.
|
|
||||||
func TestDelegatedCredentialMarshalUnmarshal(t *testing.T) {
|
|
||||||
cert := dcTestCerts["dc"]
|
|
||||||
delegatedCred, _, err := NewDelegatedCredential(cert,
|
|
||||||
ECDSAWithP256AndSHA256,
|
|
||||||
dcNow.Sub(cert.Leaf.NotBefore)+dcMaxTTL,
|
|
||||||
VersionTLS12)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
serialized, err := delegatedCred.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
delegatedCred2, err := UnmarshalDelegatedCredential(serialized)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = checkCredentialsEqual(delegatedCred, delegatedCred2)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if delegatedCred.Scheme != delegatedCred2.Scheme {
|
|
||||||
t.Errorf("scheme mismatch: got %04x; want %04x",
|
|
||||||
delegatedCred2.Scheme, delegatedCred.Scheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(delegatedCred2.Signature, delegatedCred.Signature) {
|
|
||||||
t.Error("Signature mismatch")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests the handshake and one round of application data. Returns true if the
|
// Tests the handshake and one round of application data. Returns true if the
|
||||||
// connection used a DC.
|
// connection used a DC.
|
||||||
func testConnWithDC(t *testing.T,
|
func testConnWithDC(t *testing.T, clientMsg, serverMsg string, clientConfig, serverConfig *Config) (bool, error) {
|
||||||
clientMsg, serverMsg string,
|
|
||||||
clientConfig, serverConfig *Config) (bool, error) {
|
|
||||||
|
|
||||||
ln := newLocalListener(t)
|
ln := newLocalListener(t)
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
|
|
||||||
|
// Listen for and serve a single client connection.
|
||||||
srvCh := make(chan *Conn, 1)
|
srvCh := make(chan *Conn, 1)
|
||||||
var serr error
|
var serr error
|
||||||
go func() {
|
go func() {
|
||||||
@ -346,6 +204,7 @@ func testConnWithDC(t *testing.T,
|
|||||||
srvCh <- srv
|
srvCh <- srv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Dial the server.
|
||||||
cli, err := Dial("tcp", ln.Addr().String(), clientConfig)
|
cli, err := Dial("tcp", ln.Addr().String(), clientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -363,12 +222,14 @@ func testConnWithDC(t *testing.T,
|
|||||||
}
|
}
|
||||||
buf := make([]byte, bufLen)
|
buf := make([]byte, bufLen)
|
||||||
|
|
||||||
|
// Client sends a message to the server, which is read by the server.
|
||||||
cli.Write([]byte(clientMsg))
|
cli.Write([]byte(clientMsg))
|
||||||
n, err := srv.Read(buf)
|
n, err := srv.Read(buf)
|
||||||
if n != len(clientMsg) || string(buf[:n]) != clientMsg {
|
if n != len(clientMsg) || string(buf[:n]) != clientMsg {
|
||||||
return false, fmt.Errorf("Server read = %d, buf= %q; want %d, %s", n, buf, len(clientMsg), clientMsg)
|
return false, fmt.Errorf("Server read = %d, buf= %q; want %d, %s", n, buf, len(clientMsg), clientMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server reads a message from the client, which is read by the client.
|
||||||
srv.Write([]byte(serverMsg))
|
srv.Write([]byte(serverMsg))
|
||||||
n, err = cli.Read(buf)
|
n, err = cli.Read(buf)
|
||||||
if n != len(serverMsg) || err != nil || string(buf[:n]) != serverMsg {
|
if n != len(serverMsg) || err != nil || string(buf[:n]) != serverMsg {
|
||||||
@ -389,76 +250,39 @@ func testServerGetCertificate(ch *ClientHelloInfo) (*Certificate, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if versOk && ch.AcceptsDelegatedCredential {
|
if versOk && ch.AcceptsDelegatedCredential {
|
||||||
return dcTestCerts["dc"], nil
|
return &dcTestDelegationCert, nil
|
||||||
}
|
}
|
||||||
return dcTestCerts["no dc"], nil
|
return &dcTestCert, nil
|
||||||
}
|
|
||||||
|
|
||||||
// Checks that the ciient supports the signature algorithm supported by the test
|
|
||||||
// server, and that the server has a DC for the selected protocol version.
|
|
||||||
func testServerGetDC(ch *ClientHelloInfo, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
|
|
||||||
schemeOk := false
|
|
||||||
for _, scheme := range ch.SignatureSchemes {
|
|
||||||
schemeOk = schemeOk || (scheme == dcTestDCScheme)
|
|
||||||
}
|
|
||||||
|
|
||||||
versOk := false
|
|
||||||
for _, testVers := range dcTestDCVersions {
|
|
||||||
versOk = versOk || (vers == testVers)
|
|
||||||
}
|
|
||||||
|
|
||||||
if schemeOk && versOk && ch.AcceptsDelegatedCredential {
|
|
||||||
d := dcTestDCs[vers]
|
|
||||||
return d.DelegatedCredential, d.privateKey, nil
|
|
||||||
}
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a DC signed with a bad version number.
|
|
||||||
func testServerGetInvalidDC(ch *ClientHelloInfo, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
|
|
||||||
d := dcTestDCs[versionInvalidDC]
|
|
||||||
return d.DelegatedCredential, d.privateKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a DC with the wrong private key.
|
|
||||||
func testServerGetMalformedDC(ch *ClientHelloInfo, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
|
|
||||||
if vers == VersionTLS12 {
|
|
||||||
d := dcTestDCs[versionMalformedDC12]
|
|
||||||
return d.DelegatedCredential, d.privateKey, nil
|
|
||||||
} else if vers == VersionTLS13 {
|
|
||||||
d := dcTestDCs[versionMalformedDC13]
|
|
||||||
return d.DelegatedCredential, d.privateKey, nil
|
|
||||||
} else {
|
|
||||||
return nil, nil, fmt.Errorf("testServerGetMalformedDC: unsupported version %x", vers)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Various test cases for handshakes involving DCs.
|
||||||
var dcTests = []struct {
|
var dcTests = []struct {
|
||||||
clientDC bool
|
clientDC bool
|
||||||
serverDC bool
|
serverDC bool
|
||||||
clientSkipVerify bool
|
clientSkipVerify bool
|
||||||
clientMaxVers uint16
|
clientMaxVers uint16
|
||||||
serverMaxVers uint16
|
serverMaxVers uint16
|
||||||
useMalformedDC bool
|
nowOffset time.Duration
|
||||||
useInvalidDC bool
|
dcTestName string
|
||||||
expectSuccess bool
|
expectSuccess bool
|
||||||
expectDC bool
|
expectDC bool
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{true, true, false, VersionTLS12, VersionTLS12, false, false, true, true, "tls12"},
|
{true, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, true, "tls12"},
|
||||||
{true, true, false, VersionTLS13, VersionTLS13, false, false, true, true, "tls13"},
|
{true, true, false, VersionTLS13, VersionTLS13, 0, "tls13", true, true, "tls13"},
|
||||||
{true, true, false, VersionTLS12, VersionTLS12, true, false, false, false, "tls12, malformed dc"},
|
{true, true, false, VersionTLS12, VersionTLS12, 0, "malformed12", false, false, "tls12, malformed dc"},
|
||||||
{true, true, false, VersionTLS13, VersionTLS13, true, false, false, false, "tls13, malformed dc"},
|
{true, true, false, VersionTLS13, VersionTLS13, 0, "malformed13", false, false, "tls13, malformed dc"},
|
||||||
{true, true, true, VersionTLS12, VersionTLS12, false, true, true, true, "tls12, invalid dc, skip verify"},
|
{true, true, true, VersionTLS12, VersionTLS12, 0, "invalid", true, true, "tls12, invalid dc, skip verify"},
|
||||||
{true, true, true, VersionTLS13, VersionTLS13, false, true, true, true, "tls13, invalid dc, skip verify"},
|
{true, true, true, VersionTLS13, VersionTLS13, 0, "invalid", true, true, "tls13, invalid dc, skip verify"},
|
||||||
{false, true, false, VersionTLS12, VersionTLS12, false, false, true, false, "client no dc"},
|
{false, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "client no dc"},
|
||||||
{true, false, false, VersionTLS12, VersionTLS12, false, false, true, false, "server no dc"},
|
{true, false, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "server no dc"},
|
||||||
{true, true, false, VersionTLS11, VersionTLS12, false, false, true, false, "client old"},
|
{true, true, false, VersionTLS11, VersionTLS12, 0, "tls12", true, false, "client old"},
|
||||||
{true, true, false, VersionTLS12, VersionTLS11, false, false, true, false, "server old"},
|
{true, true, false, VersionTLS12, VersionTLS11, 0, "tls12", true, false, "server old"},
|
||||||
|
{true, true, false, VersionTLS13, VersionTLS13, dcMaxTTL, "tls13", false, false, "expired dc"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests the handshake with the delegated credential extension.
|
// Tests the handshake with the delegated credential extension for each test
|
||||||
|
// case in dcTests.
|
||||||
func TestDCHandshake(t *testing.T) {
|
func TestDCHandshake(t *testing.T) {
|
||||||
serverMsg := "hello"
|
serverMsg := "hello"
|
||||||
clientMsg := "world"
|
clientMsg := "world"
|
||||||
@ -468,24 +292,36 @@ func TestDCHandshake(t *testing.T) {
|
|||||||
serverConfig.GetCertificate = testServerGetCertificate
|
serverConfig.GetCertificate = testServerGetCertificate
|
||||||
|
|
||||||
for i, test := range dcTests {
|
for i, test := range dcTests {
|
||||||
clientConfig.AcceptDelegatedCredential = test.clientDC
|
clientConfig.MaxVersion = test.clientMaxVers
|
||||||
|
serverConfig.MaxVersion = test.serverMaxVers
|
||||||
clientConfig.InsecureSkipVerify = test.clientSkipVerify
|
clientConfig.InsecureSkipVerify = test.clientSkipVerify
|
||||||
|
clientConfig.AcceptDelegatedCredential = test.clientDC
|
||||||
|
clientConfig.Time = func() time.Time {
|
||||||
|
return dcTestNow.Add(time.Duration(test.nowOffset))
|
||||||
|
}
|
||||||
|
|
||||||
if test.serverDC {
|
if test.serverDC {
|
||||||
if test.useInvalidDC {
|
serverConfig.GetDelegatedCredential = func(
|
||||||
serverConfig.GetDelegatedCredential = testServerGetInvalidDC
|
ch *ClientHelloInfo, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
|
||||||
} else if test.useMalformedDC {
|
for _, t := range dcTestDCs {
|
||||||
serverConfig.GetDelegatedCredential = testServerGetMalformedDC
|
if t.Name == test.dcTestName {
|
||||||
} else {
|
dc, err := UnmarshalDelegatedCredential(t.DC)
|
||||||
serverConfig.GetDelegatedCredential = testServerGetDC
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
sk, err := x509.ParseECPrivateKey(t.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return dc, sk, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil, fmt.Errorf("Test DC with name '%s' not found", test.dcTestName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
serverConfig.GetDelegatedCredential = nil
|
serverConfig.GetDelegatedCredential = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfig.MaxVersion = test.clientMaxVers
|
|
||||||
serverConfig.MaxVersion = test.serverMaxVers
|
|
||||||
|
|
||||||
usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig)
|
usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig)
|
||||||
if err != nil && test.expectSuccess {
|
if err != nil && test.expectSuccess {
|
||||||
t.Errorf("test #%d (%s) fails: %s", i+1, test.name, err)
|
t.Errorf("test #%d (%s) fails: %s", i+1, test.name, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user