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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"testing"
|
||||
"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
|
||||
// crypto/tls directory:
|
||||
//
|
||||
@ -68,34 +59,80 @@ zP3NGxnDVqlMX+HI1+IuFXgQTVWvBdxPkw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
`
|
||||
|
||||
// Invalid TLS versions used for testing purposes.
|
||||
const (
|
||||
versionInvalidDC uint16 = 0xff00
|
||||
versionMalformedDC12 uint16 = 0xff12
|
||||
versionMalformedDC13 uint16 = 0xff13
|
||||
)
|
||||
var dcTestDCsPEM = `-----BEGIN DC TEST DATA-----
|
||||
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
|
||||
HJbn52hmB027JEIMPWsxKxPkr7udk7Q=
|
||||
-----END DC TEST DATA-----
|
||||
`
|
||||
|
||||
var dcTestConfig *Config
|
||||
var dcTestCerts map[string]*Certificate
|
||||
var dcTestDCs map[uint16]dcWithPrivateKey
|
||||
var dcNow time.Time
|
||||
var dcTestDCScheme = ECDSAWithP521AndSHA512
|
||||
var dcTestDCVersions = []uint16{
|
||||
VersionTLS12,
|
||||
VersionTLS13,
|
||||
VersionTLS13Draft23,
|
||||
versionInvalidDC,
|
||||
type dcTestDC struct {
|
||||
Name string
|
||||
Version int
|
||||
Scheme int
|
||||
DC []byte
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
var dcTestDCs []dcTestDC
|
||||
var dcTestConfig *Config
|
||||
var dcTestDelegationCert Certificate
|
||||
var dcTestCert Certificate
|
||||
var dcTestNow time.Time
|
||||
|
||||
func init() {
|
||||
|
||||
// Use a static time for testing at whcih time the test certificates are
|
||||
// valid.
|
||||
dcNow = time.Date(2018, 07, 03, 18, 0, 0, 234234, time.UTC)
|
||||
// Parse the PEM-encoded DER block containing the test DCs.
|
||||
block, _ := pem.Decode([]byte(dcTestDCsPEM))
|
||||
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{
|
||||
Time: func() time.Time {
|
||||
return dcNow
|
||||
return dcTestNow
|
||||
},
|
||||
Rand: zeroSource{},
|
||||
Certificates: nil,
|
||||
@ -104,230 +141,51 @@ func init() {
|
||||
CipherSuites: allCipherSuites(),
|
||||
}
|
||||
|
||||
// The certificates of the server.
|
||||
dcTestCerts = make(map[string]*Certificate)
|
||||
var err error
|
||||
|
||||
// The delegation certificate.
|
||||
dcCert := new(Certificate)
|
||||
*dcCert, err = X509KeyPair([]byte(delegatorCertPEM), []byte(delegatorKeyPEM))
|
||||
dcTestDelegationCert, err = X509KeyPair([]byte(delegatorCertPEM), []byte(delegatorKeyPEM))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dcCert.Leaf, err = x509.ParseCertificate(dcCert.Certificate[0])
|
||||
dcTestDelegationCert.Leaf, err = x509.ParseCertificate(dcTestDelegationCert.Certificate[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dcTestCerts["dc"] = dcCert
|
||||
|
||||
// The standard certificate.
|
||||
ndcCert := new(Certificate)
|
||||
*ndcCert, err = X509KeyPair([]byte(nonDelegatorCertPEM), []byte(nonDelegatorKeyPEM))
|
||||
// A certificate without the the DelegationUsage extension for X.509.
|
||||
dcTestCert, err = X509KeyPair([]byte(nonDelegatorCertPEM), []byte(nonDelegatorKeyPEM))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ndcCert.Leaf, err = x509.ParseCertificate(ndcCert.Certificate[0])
|
||||
dcTestCert.Leaf, err = x509.ParseCertificate(dcTestCert.Certificate[0])
|
||||
if err != nil {
|
||||
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()
|
||||
|
||||
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 {
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
dcTestConfig.RootCAs.AddCert(ndcRoot)
|
||||
|
||||
// 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")
|
||||
}
|
||||
dcTestConfig.RootCAs.AddCert(root)
|
||||
}
|
||||
|
||||
// Tests the handshake and one round of application data. Returns true if the
|
||||
// connection used a DC.
|
||||
func testConnWithDC(t *testing.T,
|
||||
clientMsg, serverMsg string,
|
||||
clientConfig, serverConfig *Config) (bool, error) {
|
||||
|
||||
func testConnWithDC(t *testing.T, clientMsg, serverMsg string, clientConfig, serverConfig *Config) (bool, error) {
|
||||
ln := newLocalListener(t)
|
||||
defer ln.Close()
|
||||
|
||||
// Listen for and serve a single client connection.
|
||||
srvCh := make(chan *Conn, 1)
|
||||
var serr error
|
||||
go func() {
|
||||
@ -346,6 +204,7 @@ func testConnWithDC(t *testing.T,
|
||||
srvCh <- srv
|
||||
}()
|
||||
|
||||
// Dial the server.
|
||||
cli, err := Dial("tcp", ln.Addr().String(), clientConfig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -363,12 +222,14 @@ func testConnWithDC(t *testing.T,
|
||||
}
|
||||
buf := make([]byte, bufLen)
|
||||
|
||||
// Client sends a message to the server, which is read by the server.
|
||||
cli.Write([]byte(clientMsg))
|
||||
n, err := srv.Read(buf)
|
||||
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)
|
||||
}
|
||||
|
||||
// Server reads a message from the client, which is read by the client.
|
||||
srv.Write([]byte(serverMsg))
|
||||
n, err = cli.Read(buf)
|
||||
if n != len(serverMsg) || err != nil || string(buf[:n]) != serverMsg {
|
||||
@ -389,76 +250,39 @@ func testServerGetCertificate(ch *ClientHelloInfo) (*Certificate, error) {
|
||||
}
|
||||
|
||||
if versOk && ch.AcceptsDelegatedCredential {
|
||||
return dcTestCerts["dc"], nil
|
||||
return &dcTestDelegationCert, nil
|
||||
}
|
||||
return dcTestCerts["no dc"], 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)
|
||||
}
|
||||
|
||||
return &dcTestCert, nil
|
||||
}
|
||||
|
||||
// Various test cases for handshakes involving DCs.
|
||||
var dcTests = []struct {
|
||||
clientDC bool
|
||||
serverDC bool
|
||||
clientSkipVerify bool
|
||||
clientMaxVers uint16
|
||||
serverMaxVers uint16
|
||||
useMalformedDC bool
|
||||
useInvalidDC bool
|
||||
nowOffset time.Duration
|
||||
dcTestName string
|
||||
expectSuccess bool
|
||||
expectDC bool
|
||||
name string
|
||||
}{
|
||||
{true, true, false, VersionTLS12, VersionTLS12, false, false, true, true, "tls12"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, false, false, true, true, "tls13"},
|
||||
{true, true, false, VersionTLS12, VersionTLS12, true, false, false, false, "tls12, malformed dc"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, true, false, false, false, "tls13, malformed dc"},
|
||||
{true, true, true, VersionTLS12, VersionTLS12, false, true, true, true, "tls12, invalid dc, skip verify"},
|
||||
{true, true, true, VersionTLS13, VersionTLS13, false, true, true, true, "tls13, invalid dc, skip verify"},
|
||||
{false, true, false, VersionTLS12, VersionTLS12, false, false, true, false, "client no dc"},
|
||||
{true, false, false, VersionTLS12, VersionTLS12, false, false, true, false, "server no dc"},
|
||||
{true, true, false, VersionTLS11, VersionTLS12, false, false, true, false, "client old"},
|
||||
{true, true, false, VersionTLS12, VersionTLS11, false, false, true, false, "server old"},
|
||||
{true, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, true, "tls12"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "tls13", true, true, "tls13"},
|
||||
{true, true, false, VersionTLS12, VersionTLS12, 0, "malformed12", false, false, "tls12, malformed dc"},
|
||||
{true, true, false, VersionTLS13, VersionTLS13, 0, "malformed13", false, false, "tls13, malformed dc"},
|
||||
{true, true, true, VersionTLS12, VersionTLS12, 0, "invalid", true, true, "tls12, invalid dc, skip verify"},
|
||||
{true, true, true, VersionTLS13, VersionTLS13, 0, "invalid", true, true, "tls13, invalid dc, skip verify"},
|
||||
{false, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "client no dc"},
|
||||
{true, false, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "server no dc"},
|
||||
{true, true, false, VersionTLS11, VersionTLS12, 0, "tls12", true, false, "client 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) {
|
||||
serverMsg := "hello"
|
||||
clientMsg := "world"
|
||||
@ -468,24 +292,36 @@ func TestDCHandshake(t *testing.T) {
|
||||
serverConfig.GetCertificate = testServerGetCertificate
|
||||
|
||||
for i, test := range dcTests {
|
||||
clientConfig.AcceptDelegatedCredential = test.clientDC
|
||||
clientConfig.MaxVersion = test.clientMaxVers
|
||||
serverConfig.MaxVersion = test.serverMaxVers
|
||||
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.useInvalidDC {
|
||||
serverConfig.GetDelegatedCredential = testServerGetInvalidDC
|
||||
} else if test.useMalformedDC {
|
||||
serverConfig.GetDelegatedCredential = testServerGetMalformedDC
|
||||
} else {
|
||||
serverConfig.GetDelegatedCredential = testServerGetDC
|
||||
serverConfig.GetDelegatedCredential = func(
|
||||
ch *ClientHelloInfo, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
|
||||
for _, t := range dcTestDCs {
|
||||
if t.Name == test.dcTestName {
|
||||
dc, err := UnmarshalDelegatedCredential(t.DC)
|
||||
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 {
|
||||
serverConfig.GetDelegatedCredential = nil
|
||||
}
|
||||
|
||||
clientConfig.MaxVersion = test.clientMaxVers
|
||||
serverConfig.MaxVersion = test.serverMaxVers
|
||||
|
||||
usedDC, err := testConnWithDC(t, clientMsg, serverMsg, clientConfig, serverConfig)
|
||||
if err != nil && test.expectSuccess {
|
||||
t.Errorf("test #%d (%s) fails: %s", i+1, test.name, err)
|
||||
|
Loading…
Reference in New Issue
Block a user