]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: Improve TLS Client Authentication
authorJeff R. Allen <jra@nella.org>
Thu, 5 Jan 2012 17:05:38 +0000 (12:05 -0500)
committerAdam Langley <agl@golang.org>
Thu, 5 Jan 2012 17:05:38 +0000 (12:05 -0500)
Fix incorrect marshal/unmarshal of certificateRequest.
Add support for configuring client-auth on the server side.
Fix the certificate selection in the client side.
Update generate_cert.go to new time package

Fixes #2521.

R=krautz, agl, bradfitz
CC=golang-dev, mikkel
https://golang.org/cl/5448093

src/pkg/crypto/tls/common.go
src/pkg/crypto/tls/handshake_client.go
src/pkg/crypto/tls/handshake_messages.go
src/pkg/crypto/tls/handshake_server.go
src/pkg/crypto/tls/handshake_server_test.go
src/pkg/crypto/tls/tls.go
src/pkg/crypto/x509/cert_pool.go

index a461ad951b011447f6bf4ed43f88a5dc1ad8548a..25f7a920cd380e066ef84a98456113477e964ed5 100644 (file)
@@ -111,6 +111,18 @@ type ConnectionState struct {
        VerifiedChains [][]*x509.Certificate
 }
 
+// ClientAuthType declares the policy the server will follow for
+// TLS Client Authentication.
+type ClientAuthType int
+
+const (
+       NoClientCert ClientAuthType = iota
+       RequestClientCert
+       RequireAnyClientCert
+       VerifyClientCertIfGiven
+       RequireAndVerifyClientCert
+)
+
 // A Config structure is used to configure a TLS client or server. After one
 // has been passed to a TLS function it must not be modified.
 type Config struct {
@@ -120,7 +132,7 @@ type Config struct {
        Rand io.Reader
 
        // Time returns the current time as the number of seconds since the epoch.
-       // If Time is nil, TLS uses the system time.Seconds.
+       // If Time is nil, TLS uses time.Now.
        Time func() time.Time
 
        // Certificates contains one or more certificate chains
@@ -148,11 +160,14 @@ type Config struct {
        // hosting.
        ServerName string
 
-       // AuthenticateClient controls whether a server will request a certificate
-       // from the client. It does not require that the client send a
-       // certificate nor does it require that the certificate sent be
-       // anything more than self-signed.
-       AuthenticateClient bool
+       // ClientAuth determines the server's policy for
+       // TLS Client Authentication. The default is NoClientCert.
+       ClientAuth ClientAuthType
+
+       // ClientCAs defines the set of root certificate authorities
+       // that servers use if required to verify a client certificate
+       // by the policy in ClientAuth.
+       ClientCAs *x509.CertPool
 
        // InsecureSkipVerify controls whether a client verifies the
        // server's certificate chain and host name.
@@ -259,6 +274,11 @@ type Certificate struct {
        // OCSPStaple contains an optional OCSP response which will be served
        // to clients that request it.
        OCSPStaple []byte
+       // Leaf is the parsed form of the leaf certificate, which may be
+       // initialized using x509.ParseCertificate to reduce per-handshake
+       // processing for TLS clients doing client authentication. If nil, the
+       // leaf certificate will be parsed as needed.
+       Leaf *x509.Certificate
 }
 
 // A TLS record.
index 73648002bd58bd74db619cb74a2fd89ac7cc322e..632ceea9c1a2adbdfb7261cd373666770d519c6c 100644 (file)
@@ -5,12 +5,14 @@
 package tls
 
 import (
+       "bytes"
        "crypto"
        "crypto/rsa"
        "crypto/subtle"
        "crypto/x509"
        "errors"
        "io"
+       "strconv"
 )
 
 func (c *Conn) clientHandshake() error {
@@ -162,10 +164,23 @@ func (c *Conn) clientHandshake() error {
                }
        }
 
-       transmitCert := false
+       var certToSend *Certificate
        certReq, ok := msg.(*certificateRequestMsg)
        if ok {
-               // We only accept certificates with RSA keys.
+               // RFC 4346 on the certificateAuthorities field:
+               // A list of the distinguished names of acceptable certificate
+               // authorities. These distinguished names may specify a desired
+               // distinguished name for a root CA or for a subordinate CA;
+               // thus, this message can be used to describe both known roots
+               // and a desired authorization space. If the
+               // certificate_authorities list is empty then the client MAY
+               // send any certificate of the appropriate
+               // ClientCertificateType, unless there is some external
+               // arrangement to the contrary.
+
+               finishedHash.Write(certReq.marshal())
+
+               // For now, we only know how to sign challenges with RSA
                rsaAvail := false
                for _, certType := range certReq.certificateTypes {
                        if certType == certTypeRSASign {
@@ -174,23 +189,41 @@ func (c *Conn) clientHandshake() error {
                        }
                }
 
-               // For now, only send a certificate back if the server gives us an
-               // empty list of certificateAuthorities.
-               //
-               // RFC 4346 on the certificateAuthorities field:
-               // A list of the distinguished names of acceptable certificate
-               // authorities.  These distinguished names may specify a desired
-               // distinguished name for a root CA or for a subordinate CA; thus,
-               // this message can be used to describe both known roots and a
-               // desired authorization space.  If the certificate_authorities
-               // list is empty then the client MAY send any certificate of the
-               // appropriate ClientCertificateType, unless there is some
-               // external arrangement to the contrary.
-               if rsaAvail && len(certReq.certificateAuthorities) == 0 {
-                       transmitCert = true
-               }
+               // We need to search our list of client certs for one
+               // where SignatureAlgorithm is RSA and the Issuer is in
+               // certReq.certificateAuthorities
+       findCert:
+               for i, cert := range c.config.Certificates {
+                       if !rsaAvail {
+                               continue
+                       }
 
-               finishedHash.Write(certReq.marshal())
+                       leaf := cert.Leaf
+                       if leaf == nil {
+                               if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
+                                       c.sendAlert(alertInternalError)
+                                       return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+                               }
+                       }
+
+                       if leaf.PublicKeyAlgorithm != x509.RSA {
+                               continue
+                       }
+
+                       if len(certReq.certificateAuthorities) == 0 {
+                               // they gave us an empty list, so just take the
+                               // first RSA cert from c.config.Certificates
+                               certToSend = &cert
+                               break
+                       }
+
+                       for _, ca := range certReq.certificateAuthorities {
+                               if bytes.Equal(leaf.RawIssuer, ca) {
+                                       certToSend = &cert
+                                       break findCert
+                               }
+                       }
+               }
 
                msg, err = c.readHandshake()
                if err != nil {
@@ -204,17 +237,9 @@ func (c *Conn) clientHandshake() error {
        }
        finishedHash.Write(shd.marshal())
 
-       var cert *x509.Certificate
-       if transmitCert {
+       if certToSend != nil {
                certMsg = new(certificateMsg)
-               if len(c.config.Certificates) > 0 {
-                       cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
-                       if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
-                               certMsg.certificates = c.config.Certificates[0].Certificate
-                       } else {
-                               cert = nil
-                       }
-               }
+               certMsg.certificates = certToSend.Certificate
                finishedHash.Write(certMsg.marshal())
                c.writeRecord(recordTypeHandshake, certMsg.marshal())
        }
@@ -229,7 +254,7 @@ func (c *Conn) clientHandshake() error {
                c.writeRecord(recordTypeHandshake, ckx.marshal())
        }
 
-       if cert != nil {
+       if certToSend != nil {
                certVerify := new(certificateVerifyMsg)
                digest := make([]byte, 0, 36)
                digest = finishedHash.serverMD5.Sum(digest)
index 5438e749ce8b8713a7955617a4444e3947835e83..e1517cc794ff21c8eb474ab094a7e9d8e1f5b718 100644 (file)
@@ -881,9 +881,11 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
        // See http://tools.ietf.org/html/rfc4346#section-7.4.4
        length := 1 + len(m.certificateTypes) + 2
+       casLength := 0
        for _, ca := range m.certificateAuthorities {
-               length += 2 + len(ca)
+               casLength += 2 + len(ca)
        }
+       length += casLength
 
        x = make([]byte, 4+length)
        x[0] = typeCertificateRequest
@@ -895,10 +897,8 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
        copy(x[5:], m.certificateTypes)
        y := x[5+len(m.certificateTypes):]
-
-       numCA := len(m.certificateAuthorities)
-       y[0] = uint8(numCA >> 8)
-       y[1] = uint8(numCA)
+       y[0] = uint8(casLength >> 8)
+       y[1] = uint8(casLength)
        y = y[2:]
        for _, ca := range m.certificateAuthorities {
                y[0] = uint8(len(ca) >> 8)
@@ -909,7 +909,6 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
        }
 
        m.raw = x
-
        return
 }
 
@@ -937,31 +936,34 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
        }
 
        data = data[numCertTypes:]
+
        if len(data) < 2 {
                return false
        }
-
-       numCAs := uint16(data[0])<<16 | uint16(data[1])
+       casLength := uint16(data[0])<<8 | uint16(data[1])
        data = data[2:]
+       if len(data) < int(casLength) {
+               return false
+       }
+       cas := make([]byte, casLength)
+       copy(cas, data)
+       data = data[casLength:]
 
-       m.certificateAuthorities = make([][]byte, numCAs)
-       for i := uint16(0); i < numCAs; i++ {
-               if len(data) < 2 {
+       m.certificateAuthorities = nil
+       for len(cas) > 0 {
+               if len(cas) < 2 {
                        return false
                }
-               caLen := uint16(data[0])<<16 | uint16(data[1])
+               caLen := uint16(cas[0])<<8 | uint16(cas[1])
+               cas = cas[2:]
 
-               data = data[2:]
-               if len(data) < int(caLen) {
+               if len(cas) < int(caLen) {
                        return false
                }
 
-               ca := make([]byte, caLen)
-               copy(ca, data)
-               m.certificateAuthorities[i] = ca
-               data = data[caLen:]
+               m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
+               cas = cas[caLen:]
        }
-
        if len(data) > 0 {
                return false
        }
index 89c000dd6e9b04fed616564dc864843b842d9e92..fb53767f3e08c50e6cb857e3a6a60387a30a4a3d 100644 (file)
@@ -150,14 +150,19 @@ FindCipherSuite:
                c.writeRecord(recordTypeHandshake, skx.marshal())
        }
 
-       if config.AuthenticateClient {
+       if config.ClientAuth >= RequestClientCert {
                // Request a client certificate
                certReq := new(certificateRequestMsg)
                certReq.certificateTypes = []byte{certTypeRSASign}
+
                // An empty list of certificateAuthorities signals to
                // the client that it may send any certificate in response
-               // to our request.
-
+               // to our request. When we know the CAs we trust, then
+               // we can send them down, so that the client can choose
+               // an appropriate certificate to give to us.
+               if config.ClientCAs != nil {
+                       certReq.certificateAuthorities = config.ClientCAs.Subjects()
+               }
                finishedHash.Write(certReq.marshal())
                c.writeRecord(recordTypeHandshake, certReq.marshal())
        }
@@ -166,52 +171,87 @@ FindCipherSuite:
        finishedHash.Write(helloDone.marshal())
        c.writeRecord(recordTypeHandshake, helloDone.marshal())
 
-       var pub *rsa.PublicKey
-       if config.AuthenticateClient {
-               // Get client certificate
-               msg, err = c.readHandshake()
-               if err != nil {
-                       return err
-               }
-               certMsg, ok = msg.(*certificateMsg)
-               if !ok {
-                       return c.sendAlert(alertUnexpectedMessage)
+       var pub *rsa.PublicKey // public key for client auth, if any
+
+       msg, err = c.readHandshake()
+       if err != nil {
+               return err
+       }
+
+       // If we requested a client certificate, then the client must send a
+       // certificate message, even if it's empty.
+       if config.ClientAuth >= RequestClientCert {
+               if certMsg, ok = msg.(*certificateMsg); !ok {
+                       return c.sendAlert(alertHandshakeFailure)
                }
                finishedHash.Write(certMsg.marshal())
 
+               if len(certMsg.certificates) == 0 {
+                       // The client didn't actually send a certificate
+                       switch config.ClientAuth {
+                       case RequireAnyClientCert, RequireAndVerifyClientCert:
+                               c.sendAlert(alertBadCertificate)
+                               return errors.New("tls: client didn't provide a certificate")
+                       }
+               }
+
                certs := make([]*x509.Certificate, len(certMsg.certificates))
                for i, asn1Data := range certMsg.certificates {
-                       cert, err := x509.ParseCertificate(asn1Data)
-                       if err != nil {
+                       if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
                                c.sendAlert(alertBadCertificate)
-                               return errors.New("could not parse client's certificate: " + err.Error())
+                               return errors.New("tls: failed to parse client certificate: " + err.Error())
                        }
-                       certs[i] = cert
                }
 
-               // TODO(agl): do better validation of certs: max path length, name restrictions etc.
-               for i := 1; i < len(certs); i++ {
-                       if err := certs[i-1].CheckSignatureFrom(certs[i]); err != nil {
+               if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+                       opts := x509.VerifyOptions{
+                               Roots:         c.config.ClientCAs,
+                               CurrentTime:   c.config.time(),
+                               Intermediates: x509.NewCertPool(),
+                       }
+
+                       for i, cert := range certs {
+                               if i == 0 {
+                                       continue
+                               }
+                               opts.Intermediates.AddCert(cert)
+                       }
+
+                       chains, err := certs[0].Verify(opts)
+                       if err != nil {
                                c.sendAlert(alertBadCertificate)
-                               return errors.New("could not validate certificate signature: " + err.Error())
+                               return errors.New("tls: failed to verify client's certificate: " + err.Error())
                        }
+
+                       ok := false
+                       for _, ku := range certs[0].ExtKeyUsage {
+                               if ku == x509.ExtKeyUsageClientAuth {
+                                       ok = true
+                                       break
+                               }
+                       }
+                       if !ok {
+                               c.sendAlert(alertHandshakeFailure)
+                               return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+                       }
+
+                       c.verifiedChains = chains
                }
 
                if len(certs) > 0 {
-                       key, ok := certs[0].PublicKey.(*rsa.PublicKey)
-                       if !ok {
+                       if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
                                return c.sendAlert(alertUnsupportedCertificate)
                        }
-                       pub = key
                        c.peerCertificates = certs
                }
+
+               msg, err = c.readHandshake()
+               if err != nil {
+                       return err
+               }
        }
 
        // Get client key exchange
-       msg, err = c.readHandshake()
-       if err != nil {
-               return err
-       }
        ckx, ok := msg.(*clientKeyExchangeMsg)
        if !ok {
                return c.sendAlert(alertUnexpectedMessage)
index d98e13decf677596ee8bcf77c2a75ad533ef9922..4bff5327e2c7e242e558fd16655bde4189efa30b 100644 (file)
@@ -7,9 +7,12 @@ package tls
 import (
        "bytes"
        "crypto/rsa"
+       "crypto/x509"
        "encoding/hex"
+       "encoding/pem"
        "flag"
        "io"
+       "log"
        "math/big"
        "net"
        "strconv"
@@ -109,16 +112,18 @@ func TestClose(t *testing.T) {
        }
 }
 
-func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) {
        c, s := net.Pipe()
        srv := Server(s, config)
+       pchan := make(chan []*x509.Certificate, 1)
        go func() {
                srv.Write([]byte("hello, world\n"))
                srv.Close()
                s.Close()
+               st := srv.ConnectionState()
+               pchan <- st.PeerCertificates
        }()
 
-       defer c.Close()
        for i, b := range serverScript {
                if i%2 == 0 {
                        c.Write(b)
@@ -133,34 +138,66 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
                        t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
                }
        }
+       c.Close()
+
+       if peers != nil {
+               gotpeers := <-pchan
+               if len(peers) == len(gotpeers) {
+                       for i, _ := range peers {
+                               if !peers[i].Equal(gotpeers[i]) {
+                                       t.Fatalf("%s: mismatch on peer cert %d", name, i)
+                               }
+                       }
+               } else {
+                       t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", name, len(peers), len(gotpeers))
+               }
+       }
 }
 
 func TestHandshakeServerRC4(t *testing.T) {
-       testServerScript(t, "RC4", rc4ServerScript, testConfig)
+       testServerScript(t, "RC4", rc4ServerScript, testConfig, nil)
 }
 
 func TestHandshakeServer3DES(t *testing.T) {
        des3Config := new(Config)
        *des3Config = *testConfig
        des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}
-       testServerScript(t, "3DES", des3ServerScript, des3Config)
+       testServerScript(t, "3DES", des3ServerScript, des3Config, nil)
 }
 
 func TestHandshakeServerAES(t *testing.T) {
        aesConfig := new(Config)
        *aesConfig = *testConfig
        aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
-       testServerScript(t, "AES", aesServerScript, aesConfig)
+       testServerScript(t, "AES", aesServerScript, aesConfig, nil)
 }
 
 func TestHandshakeServerSSLv3(t *testing.T) {
-       testServerScript(t, "SSLv3", sslv3ServerScript, testConfig)
+       testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil)
+}
+
+type clientauthTest struct {
+       name       string
+       clientauth ClientAuthType
+       peers      []*x509.Certificate
+       script     [][]byte
+}
+
+func TestClientAuth(t *testing.T) {
+       for _, cat := range clientauthTests {
+               t.Log("running", cat.name)
+               cfg := new(Config)
+               *cfg = *testConfig
+               cfg.ClientAuth = cat.clientauth
+               testServerScript(t, cat.name, cat.script, cfg, cat.peers)
+       }
 }
 
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
 var testCipherSuites = flag.String("ciphersuites",
        "0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
        "cipher suites to accept in serving mode")
+var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
 
 func TestRunServer(t *testing.T) {
        if !*serve {
@@ -177,6 +214,8 @@ func TestRunServer(t *testing.T) {
                testConfig.CipherSuites[i] = uint16(suite)
        }
 
+       testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+
        l, err := Listen("tcp", ":10443", testConfig)
        if err != nil {
                t.Fatal(err)
@@ -185,13 +224,23 @@ func TestRunServer(t *testing.T) {
        for {
                c, err := l.Accept()
                if err != nil {
+                       log.Printf("error from TLS handshake: %s", err)
                        break
                }
+
                _, err = c.Write([]byte("hello, world\n"))
                if err != nil {
-                       t.Errorf("error from TLS: %s", err)
-                       break
+                       log.Printf("error from TLS: %s", err)
+                       continue
                }
+
+               st := c.(*Conn).ConnectionState()
+               if len(st.PeerCertificates) > 0 {
+                       log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
+               } else {
+                       log.Print("Handling request from anon client")
+               }
+
                c.Close()
        }
 }
@@ -221,6 +270,18 @@ var testPrivateKey = &rsa.PrivateKey{
        },
 }
 
+func loadPEMCert(in string) *x509.Certificate {
+       block, _ := pem.Decode([]byte(in))
+       if block.Type == "CERTIFICATE" && len(block.Headers) == 0 {
+               cert, err := x509.ParseCertificate(block.Bytes)
+               if err == nil {
+                       return cert
+               }
+               panic("error parsing cert")
+       }
+       panic("error parsing PEM")
+}
+
 // Script of interaction with gnutls implementation.
 // The values for this test are obtained by building and running in server mode:
 //   % gotest -test.run "TestRunServer" -serve
@@ -229,23 +290,22 @@ var testPrivateKey = &rsa.PrivateKey{
 //   % python parse-gnutls-cli-debug-log.py < /tmp/log
 var rc4ServerScript = [][]byte{
        {
-               0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
-               0x7b, 0x03, 0x02, 0x4d, 0x08, 0x1f, 0x5a, 0x7a,
-               0x0a, 0x92, 0x2f, 0xf0, 0x73, 0x16, 0x3a, 0x88,
-               0x14, 0x85, 0x4c, 0x98, 0x15, 0x7b, 0x65, 0xe0,
-               0x78, 0xd0, 0xed, 0xd0, 0xf3, 0x65, 0x20, 0xeb,
-               0x80, 0xd1, 0x0b, 0x00, 0x00, 0x34, 0x00, 0x33,
+               0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+               0x76, 0x03, 0x02, 0x4e, 0xdd, 0xe6, 0xa5, 0xf7,
+               0x00, 0x36, 0xf7, 0x83, 0xec, 0x93, 0x7c, 0xd2,
+               0x4d, 0xe7, 0x7b, 0xf5, 0x4c, 0xf7, 0xe3, 0x86,
+               0xe8, 0xec, 0x3b, 0xbd, 0x2c, 0x9a, 0x3f, 0x57,
+               0xf0, 0xa4, 0xd4, 0x00, 0x00, 0x34, 0x00, 0x33,
                0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
                0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
                0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
                0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
                0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
                0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-               0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
+               0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
                0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-               0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
-               0x01, 0x00, 0x01, 0x00,
+               0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
        },
 
        {
@@ -349,38 +409,46 @@ var rc4ServerScript = [][]byte{
 
        {
                0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-               0x82, 0x00, 0x80, 0x3c, 0x13, 0xd7, 0x12, 0xc1,
-               0x6a, 0xf0, 0x3f, 0x8c, 0xa1, 0x35, 0x5d, 0xc5,
-               0x89, 0x1e, 0x9e, 0xcd, 0x32, 0xc7, 0x9e, 0xe6,
-               0xae, 0xd5, 0xf1, 0xbf, 0x70, 0xd7, 0xa9, 0xef,
-               0x2c, 0x4c, 0xf4, 0x22, 0xbc, 0x17, 0x17, 0xaa,
-               0x05, 0xf3, 0x9f, 0x80, 0xf2, 0xe9, 0x82, 0x2f,
-               0x2a, 0x15, 0x54, 0x0d, 0x16, 0x0e, 0x77, 0x4c,
-               0x28, 0x3c, 0x03, 0x2d, 0x2d, 0xd7, 0xc8, 0x64,
-               0xd9, 0x59, 0x4b, 0x1c, 0xf4, 0xde, 0xff, 0x2f,
-               0xbc, 0x94, 0xaf, 0x18, 0x26, 0x37, 0xce, 0x4f,
-               0x84, 0x74, 0x2e, 0x45, 0x66, 0x7c, 0x0c, 0x54,
-               0x46, 0x36, 0x5f, 0x65, 0x21, 0x7b, 0x83, 0x8c,
-               0x6d, 0x76, 0xcd, 0x0d, 0x9f, 0xda, 0x1c, 0xa4,
-               0x6e, 0xfe, 0xb1, 0xf7, 0x09, 0x0d, 0xfb, 0x74,
-               0x66, 0x34, 0x99, 0x89, 0x7f, 0x5f, 0x77, 0x87,
-               0x4a, 0x66, 0x4b, 0xa9, 0x59, 0x57, 0xe3, 0x56,
-               0x0d, 0xdd, 0xd8, 0x14, 0x03, 0x01, 0x00, 0x01,
-               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc0, 0x4e,
-               0xd3, 0x0f, 0xb5, 0xc0, 0x57, 0xa6, 0x18, 0x80,
-               0x80, 0x6b, 0x49, 0xfe, 0xbd, 0x3a, 0x7a, 0x2c,
-               0xef, 0x70, 0xb5, 0x1c, 0xd2, 0xdf, 0x5f, 0x78,
-               0x5a, 0xd8, 0x4f, 0xa0, 0x95, 0xb4, 0xb3, 0xb5,
-               0xaa, 0x3b,
+               0x82, 0x00, 0x80, 0x39, 0xe2, 0x0f, 0x49, 0xa0,
+               0xe6, 0xe4, 0x3b, 0x0c, 0x5f, 0xce, 0x39, 0x97,
+               0x6c, 0xb6, 0x41, 0xd9, 0xe1, 0x52, 0x8f, 0x43,
+               0xb3, 0xc6, 0x4f, 0x9a, 0xe2, 0x1e, 0xb9, 0x3b,
+               0xe3, 0x72, 0x17, 0x68, 0xb2, 0x0d, 0x7b, 0x71,
+               0x33, 0x96, 0x5c, 0xf9, 0xfe, 0x18, 0x8f, 0x2f,
+               0x2b, 0x82, 0xec, 0x03, 0xf2, 0x16, 0xa8, 0xf8,
+               0x39, 0xf9, 0xbb, 0x5a, 0xd3, 0x0c, 0xc1, 0x2a,
+               0x52, 0xa1, 0x90, 0x20, 0x6b, 0x24, 0xc9, 0x55,
+               0xee, 0x05, 0xd8, 0xb3, 0x43, 0x58, 0xf6, 0x7f,
+               0x68, 0x2d, 0xb3, 0xd1, 0x1b, 0x30, 0xaa, 0xdf,
+               0xfc, 0x85, 0xf1, 0xab, 0x14, 0x51, 0x91, 0x78,
+               0x29, 0x35, 0x65, 0xe0, 0x9c, 0xf6, 0xb7, 0x35,
+               0x33, 0xdb, 0x28, 0x93, 0x4d, 0x86, 0xbc, 0xfe,
+               0xaa, 0xd1, 0xc0, 0x2e, 0x4d, 0xec, 0xa2, 0x98,
+               0xca, 0x08, 0xb2, 0x91, 0x14, 0xde, 0x97, 0x3a,
+               0xc4, 0x6b, 0x49, 0x14, 0x03, 0x01, 0x00, 0x01,
+               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x7a, 0xcb,
+               0x3b, 0x0e, 0xbb, 0x7a, 0x56, 0x39, 0xaf, 0x83,
+               0xae, 0xfd, 0x25, 0xfd, 0x64, 0xb4, 0x0c, 0x0c,
+               0x17, 0x46, 0x54, 0x2c, 0x6a, 0x07, 0x83, 0xc6,
+               0x46, 0x08, 0x0b, 0xcd, 0x15, 0x53, 0xef, 0x40,
+               0x4e, 0x56,
        },
 
        {
                0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-               0x01, 0x00, 0x24, 0x9d, 0xc9, 0xda, 0xdf, 0xeb,
-               0xc8, 0xdb, 0xf8, 0x94, 0xa5, 0xef, 0xd5, 0xfc,
-               0x89, 0x01, 0x64, 0x30, 0x77, 0x5a, 0x18, 0x4b,
-               0x16, 0x79, 0x9c, 0xf6, 0xf5, 0x09, 0x22, 0x12,
-               0x4c, 0x3e, 0xa8, 0x8e, 0x91, 0xa5, 0x24,
+               0x01, 0x00, 0x24, 0xd3, 0x72, 0xeb, 0x29, 0xb9,
+               0x15, 0x29, 0xb5, 0xe5, 0xb7, 0xef, 0x5c, 0xb2,
+               0x9d, 0xf6, 0xc8, 0x47, 0xd6, 0xa0, 0x84, 0xf0,
+               0x8c, 0xcb, 0xe6, 0xbe, 0xbc, 0xfb, 0x38, 0x90,
+               0x89, 0x60, 0xa2, 0xe8, 0xaa, 0xb3, 0x12, 0x17,
+               0x03, 0x01, 0x00, 0x21, 0x67, 0x4a, 0x3d, 0x31,
+               0x6c, 0x5a, 0x1c, 0xf9, 0x6e, 0xf1, 0xd8, 0x12,
+               0x0e, 0xb9, 0xfd, 0xfc, 0x66, 0x91, 0xd1, 0x1d,
+               0x6e, 0xe4, 0x55, 0xdd, 0x11, 0xb9, 0xb8, 0xa2,
+               0x65, 0xa1, 0x95, 0x64, 0x1c, 0x15, 0x03, 0x01,
+               0x00, 0x16, 0x9b, 0xa0, 0x24, 0xe3, 0xcb, 0xae,
+               0xad, 0x51, 0xb3, 0x63, 0x59, 0x78, 0x49, 0x24,
+               0x06, 0x6e, 0xee, 0x7a, 0xd7, 0x74, 0x53, 0x04,
        },
 }
 
@@ -878,3 +946,625 @@ var sslv3ServerScript = [][]byte{
                0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
        },
 }
+
+var clientauthTests = []clientauthTest{
+       // Server doesn't asks for cert
+       // gotest -test.run "TestRunServer" -serve -clientauth 0
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
+       //   python parse-gnutls-cli-debug-log.py
+       {"NoClientCert", NoClientCert, nil,
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe0, 0x92, 0x5d, 0xcd,
+                       0xfe, 0x0c, 0x69, 0xd4, 0x7d, 0x8e, 0xa6, 0x88,
+                       0xde, 0x72, 0x04, 0x29, 0x6a, 0x4a, 0x16, 0x23,
+                       0xd7, 0x8f, 0xbc, 0xfa, 0x80, 0x73, 0x2e, 0x12,
+                       0xb7, 0x0b, 0x39, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+                               0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+                               0x82, 0x00, 0x80, 0x10, 0xe1, 0x00, 0x3d, 0x0a,
+                               0x6b, 0x02, 0x7f, 0x97, 0xde, 0xfb, 0x65, 0x46,
+                               0x1a, 0x50, 0x4e, 0x34, 0x9a, 0xae, 0x14, 0x7e,
+                               0xec, 0xef, 0x85, 0x15, 0x3b, 0x39, 0xc2, 0x45,
+                               0x04, 0x40, 0x92, 0x71, 0xd6, 0x7e, 0xf6, 0xfd,
+                               0x4d, 0x84, 0xf7, 0xc4, 0x77, 0x99, 0x3d, 0xe2,
+                               0xc3, 0x8d, 0xb0, 0x4c, 0x74, 0xc8, 0x51, 0xec,
+                               0xb2, 0xe8, 0x6b, 0xa1, 0xd2, 0x4d, 0xd8, 0x61,
+                               0x92, 0x7a, 0x24, 0x57, 0x44, 0x4f, 0xa2, 0x1e,
+                               0x74, 0x0b, 0x06, 0x4b, 0x80, 0x34, 0x8b, 0xfe,
+                               0xc2, 0x0e, 0xc1, 0xcd, 0xab, 0x0c, 0x3f, 0x54,
+                               0xe2, 0x44, 0xe9, 0x6c, 0x2b, 0xba, 0x7b, 0x64,
+                               0xf1, 0x93, 0x65, 0x75, 0xf2, 0x35, 0xff, 0x27,
+                               0x03, 0xd5, 0x64, 0xe6, 0x8e, 0xe7, 0x7b, 0x56,
+                               0xb6, 0x61, 0x73, 0xeb, 0xa2, 0xdc, 0xa4, 0x6e,
+                               0x52, 0xac, 0xbc, 0xba, 0x11, 0xa3, 0xd2, 0x61,
+                               0x4a, 0xe0, 0xbb, 0x14, 0x03, 0x01, 0x00, 0x01,
+                               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xd2, 0x5a,
+                               0x0c, 0x2a, 0x27, 0x96, 0xba, 0xa9, 0x67, 0xd2,
+                               0x51, 0x68, 0x32, 0x68, 0x22, 0x1f, 0xb9, 0x27,
+                               0x79, 0x59, 0x28, 0xdf, 0x38, 0x1f, 0x92, 0x21,
+                               0x5d, 0x0f, 0xf4, 0xc0, 0xee, 0xb7, 0x10, 0x5a,
+                               0xa9, 0x45,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0x13, 0x6f, 0x6c, 0x71, 0x83,
+                               0x59, 0xcf, 0x32, 0x72, 0xe9, 0xce, 0xcc, 0x7a,
+                               0x6c, 0xf0, 0x72, 0x39, 0x16, 0xae, 0x40, 0x61,
+                               0xfa, 0x92, 0x4c, 0xe7, 0xf2, 0x1a, 0xd7, 0x0c,
+                               0x84, 0x76, 0x6c, 0xe9, 0x11, 0x43, 0x19, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0xc0, 0xa2, 0x13, 0x28,
+                               0x94, 0x8c, 0x5c, 0xd6, 0x79, 0xb9, 0xfe, 0xae,
+                               0x45, 0x4b, 0xc0, 0x7c, 0xae, 0x2d, 0xb4, 0x0d,
+                               0x31, 0xc4, 0xad, 0x22, 0xd7, 0x1e, 0x99, 0x1c,
+                               0x4c, 0x69, 0xab, 0x42, 0x61, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0xe1, 0x0c, 0x67, 0xf3, 0xf4, 0xb9,
+                               0x8e, 0x81, 0x8e, 0x01, 0xb8, 0xa0, 0x69, 0x8c,
+                               0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
+                       }}},
+       // Server asks for cert with empty CA list, client doesn't give it.
+       // gotest -test.run "TestRunServer" -serve -clientauth 1
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost
+       {"RequestClientCert, none given", RequestClientCert, nil,
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe0, 0x93, 0xe2, 0x47,
+                       0x06, 0xa0, 0x61, 0x0c, 0x51, 0xdd, 0xf0, 0xef,
+                       0xf4, 0x30, 0x72, 0xe1, 0xa6, 0x50, 0x68, 0x82,
+                       0x3c, 0xfb, 0xcb, 0x72, 0x5e, 0x73, 0x9d, 0xda,
+                       0x27, 0x35, 0x72, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+                               0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+                               0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
+                               0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
+                               0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x64,
+                               0x28, 0xb9, 0x3f, 0x48, 0xaf, 0x06, 0x22, 0x39,
+                               0x56, 0xd8, 0x6f, 0x63, 0x5d, 0x03, 0x48, 0x63,
+                               0x01, 0x13, 0xa2, 0xd6, 0x76, 0xc0, 0xab, 0xda,
+                               0x25, 0x30, 0x75, 0x6c, 0xaa, 0xb4, 0xdc, 0x35,
+                               0x72, 0xdc, 0xf2, 0x43, 0xe4, 0x1d, 0x82, 0xfb,
+                               0x6c, 0x64, 0xe2, 0xa7, 0x8f, 0x32, 0x67, 0x6b,
+                               0xcd, 0xd2, 0xb2, 0x36, 0x94, 0xbc, 0x6f, 0x46,
+                               0x79, 0x29, 0x42, 0xe3, 0x1a, 0xbf, 0xfb, 0x41,
+                               0xd5, 0xe3, 0xb4, 0x2a, 0xf6, 0x95, 0x6f, 0x0c,
+                               0x87, 0xb9, 0x03, 0x18, 0xa1, 0xea, 0x4a, 0xe2,
+                               0x2e, 0x0f, 0x50, 0x00, 0xc1, 0xe8, 0x8c, 0xc8,
+                               0xa2, 0xf6, 0xa4, 0x05, 0xf4, 0x38, 0x3e, 0xd9,
+                               0x6e, 0x63, 0x96, 0x0c, 0x34, 0x73, 0x90, 0x03,
+                               0x55, 0xa6, 0x34, 0xb0, 0x5e, 0x8c, 0x48, 0x40,
+                               0x25, 0x45, 0x84, 0xa6, 0x21, 0x3f, 0x81, 0x97,
+                               0xa7, 0x11, 0x09, 0x14, 0x95, 0xa5, 0xe5, 0x14,
+                               0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+                               0x00, 0x24, 0x16, 0xaa, 0x01, 0x2c, 0xa8, 0xc1,
+                               0x28, 0xaf, 0x35, 0xc1, 0xc1, 0xf3, 0x0a, 0x25,
+                               0x66, 0x6e, 0x27, 0x11, 0xa3, 0xa4, 0xd9, 0xe9,
+                               0xea, 0x15, 0x09, 0x9d, 0x28, 0xe3, 0x5b, 0x2b,
+                               0xa6, 0x25, 0xa7, 0x14, 0x24, 0x3a,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0x9a, 0xa8, 0xd6, 0x77, 0x46,
+                               0x45, 0x68, 0x9d, 0x5d, 0xa9, 0x68, 0x03, 0xe5,
+                               0xaf, 0xe8, 0xc8, 0x21, 0xc5, 0xc6, 0xc1, 0x50,
+                               0xe0, 0xd8, 0x52, 0xce, 0xa3, 0x4f, 0x2d, 0xf4,
+                               0xe3, 0xa7, 0x7d, 0x35, 0x80, 0x84, 0x12, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0x8a, 0x82, 0x0c, 0x54,
+                               0x1b, 0xeb, 0x77, 0x90, 0x2c, 0x3e, 0xbc, 0xf0,
+                               0x23, 0xcc, 0xa8, 0x9f, 0x25, 0x08, 0x12, 0xed,
+                               0x43, 0xf1, 0xf9, 0x06, 0xad, 0xa9, 0x4b, 0x97,
+                               0x82, 0xb7, 0xc4, 0x0b, 0x4c, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0x05, 0x2d, 0x9d, 0x45, 0x03, 0xb7,
+                               0xc2, 0xd1, 0xb5, 0x1a, 0x43, 0xcf, 0x1a, 0x37,
+                               0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
+                       }}},
+       // Server asks for cert with empty CA list, client gives one
+       // gotest -test.run "TestRunServer" -serve -clientauth 1
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost
+       {"RequestClientCert, client gives it", RequestClientCert,
+               []*x509.Certificate{clicert},
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
+                       0x7d, 0x46, 0x4a, 0x48, 0x97, 0x9f, 0xe5, 0x91,
+                       0x11, 0x64, 0xa7, 0x1e, 0x4d, 0xb7, 0xfe, 0x9b,
+                       0xc6, 0x63, 0xf8, 0xa4, 0xb5, 0x0b, 0x18, 0xb5,
+                       0xbd, 0x19, 0xb3, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+                               0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+                               0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+                               0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+                               0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+                               0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+                               0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+                               0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+                               0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+                               0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+                               0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+                               0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+                               0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+                               0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+                               0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+                               0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+                               0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+                               0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+                               0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+                               0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+                               0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+                               0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+                               0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+                               0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+                               0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+                               0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+                               0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+                               0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+                               0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+                               0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+                               0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+                               0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+                               0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+                               0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+                               0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+                               0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+                               0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+                               0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+                               0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+                               0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+                               0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+                               0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+                               0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+                               0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+                               0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+                               0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+                               0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+                               0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+                               0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+                               0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+                               0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+                               0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+                               0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+                               0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+                               0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+                               0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+                               0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+                               0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+                               0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+                               0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+                               0x82, 0x00, 0x80, 0xa7, 0x2f, 0xed, 0xfa, 0xc2,
+                               0xbd, 0x46, 0xa1, 0xf2, 0x69, 0xc5, 0x1d, 0xa1,
+                               0x34, 0xd6, 0xd0, 0x84, 0xf5, 0x5d, 0x8c, 0x82,
+                               0x8d, 0x98, 0x82, 0x9c, 0xd9, 0x07, 0xe0, 0xf7,
+                               0x55, 0x49, 0x4d, 0xa1, 0x48, 0x59, 0x02, 0xd3,
+                               0x84, 0x37, 0xaf, 0x01, 0xb3, 0x3a, 0xf4, 0xed,
+                               0x99, 0xbe, 0x67, 0x36, 0x19, 0x55, 0xf3, 0xf9,
+                               0xcb, 0x94, 0xe5, 0x7b, 0x8b, 0x77, 0xf2, 0x5f,
+                               0x4c, 0xfe, 0x01, 0x1f, 0x7b, 0xd7, 0x23, 0x49,
+                               0x0c, 0xcb, 0x6c, 0xb0, 0xe7, 0x77, 0xd6, 0xcf,
+                               0xa8, 0x7d, 0xdb, 0xa7, 0x14, 0xe2, 0xf5, 0xf3,
+                               0xff, 0xba, 0x23, 0xd2, 0x9a, 0x36, 0x14, 0x60,
+                               0x2a, 0x91, 0x5d, 0x2b, 0x35, 0x3b, 0xb6, 0xdd,
+                               0xcb, 0x6b, 0xdc, 0x18, 0xdc, 0x33, 0xb8, 0xb3,
+                               0xc7, 0x27, 0x7e, 0xfc, 0xd2, 0xf7, 0x97, 0x90,
+                               0x5e, 0x17, 0xac, 0x14, 0x8e, 0x0f, 0xca, 0xb5,
+                               0x6f, 0xc9, 0x2d, 0x16, 0x03, 0x01, 0x00, 0x86,
+                               0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x44, 0x7f,
+                               0xa2, 0x59, 0x60, 0x0b, 0x5a, 0xc4, 0xaf, 0x1e,
+                               0x60, 0xa5, 0x24, 0xea, 0xc1, 0xc3, 0x22, 0x21,
+                               0x6b, 0x22, 0x8b, 0x2a, 0x11, 0x82, 0x68, 0x7d,
+                               0xb9, 0xdd, 0x9c, 0x27, 0x4c, 0xc2, 0xc8, 0xa2,
+                               0x8b, 0x6b, 0x77, 0x8d, 0x3a, 0x2b, 0x8d, 0x2f,
+                               0x6a, 0x2b, 0x43, 0xd2, 0xd1, 0xc6, 0x41, 0x79,
+                               0xa2, 0x4f, 0x2b, 0xc2, 0xf7, 0xb2, 0x10, 0xad,
+                               0xa6, 0x01, 0x51, 0x51, 0x25, 0xe7, 0x58, 0x7a,
+                               0xcf, 0x3b, 0xc4, 0x29, 0xb5, 0xe5, 0xa7, 0x83,
+                               0xe6, 0xcb, 0x1e, 0xf3, 0x02, 0x0f, 0x53, 0x3b,
+                               0xb5, 0x39, 0xef, 0x9c, 0x42, 0xe0, 0xa6, 0x9b,
+                               0x2b, 0xdd, 0x60, 0xae, 0x0a, 0x73, 0x35, 0xbe,
+                               0x26, 0x10, 0x1b, 0xe9, 0xe9, 0x61, 0xab, 0x20,
+                               0xa5, 0x48, 0xc6, 0x60, 0xa6, 0x50, 0x3c, 0xfb,
+                               0xa7, 0xca, 0xb0, 0x80, 0x95, 0x1e, 0xce, 0xc7,
+                               0xbb, 0x68, 0x44, 0xdc, 0x0e, 0x0e, 0x14, 0x03,
+                               0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+                               0x24, 0xb6, 0xcd, 0x0c, 0x78, 0xfd, 0xd6, 0xff,
+                               0xbe, 0x97, 0xd5, 0x0a, 0x7d, 0x4f, 0xa1, 0x03,
+                               0x78, 0xc8, 0x61, 0x6f, 0xf2, 0x4b, 0xa8, 0x56,
+                               0x4f, 0x3c, 0xa2, 0xd9, 0xd0, 0x20, 0x13, 0x1b,
+                               0x8b, 0x36, 0xb7, 0x33, 0x9c,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0xa3, 0x43, 0x94, 0xe7, 0xdf,
+                               0xb6, 0xc3, 0x03, 0x9f, 0xc1, 0x59, 0x0c, 0xc3,
+                               0x13, 0xae, 0xed, 0xcf, 0xff, 0xf1, 0x80, 0xf3,
+                               0x13, 0x63, 0x1c, 0xf0, 0xca, 0xad, 0x9e, 0x71,
+                               0x46, 0x5f, 0x6b, 0xeb, 0x10, 0x3f, 0xe3, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0xe9, 0x80, 0x95, 0x6e,
+                               0x05, 0x55, 0x2f, 0xed, 0x4d, 0xde, 0x17, 0x3a,
+                               0x32, 0x9b, 0x2a, 0x74, 0x30, 0x4f, 0xe0, 0x9f,
+                               0x4e, 0xd3, 0x06, 0xbd, 0x3a, 0x43, 0x75, 0x8b,
+                               0x5b, 0x9a, 0xd8, 0x2e, 0x56, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
+                               0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
+                               0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
+                       }}},
+}
+
+// cert.pem and key.pem were generated with generate_cert.go
+// Thus, they have no ExtKeyUsage fields and trigger an error
+// when verification is turned on.
+
+var clicert = loadPEMCert(`
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
+bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
+MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
+MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
+hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
+ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
+E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
+p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
+hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
+GFGNEH5PlGffo05wc46QkYU=
+-----END CERTIFICATE-----
+`)
+
+/* corresponding key.pem for cert.pem is:
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
+DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
+gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
+t2WquaOu/cr5P8iEsa6lk20tf8pjKLNXeX0b1RTzK8rJLbS7nGzP3tvOhL096VtQ
+dAo4ROEaro0TzYpHmpciSvxVIeEIAAdFDObDJPKqcJAxyQJBAJizfYgK8Gzx9fsx
+hxp+VteCbVPg2euASH5Yv3K5LukRdKoSzHE2grUVQgN/LafC0eZibRanxHegYSr7
+7qaswKUCQQCEIWor/X4XTMdVj3Oj+vpiw75y/S9gh682+myZL+d/02IEkwnB098P
+RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
+saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
+Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
+qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvAMAA=
+-----END RSA PRIVATE KEY-----
+*/
index 79ab50231293045e6b0eed4f0efd88818163fb24..28e93a0be69c5165006c89be8f5058004107b43e 100644 (file)
@@ -120,7 +120,7 @@ func Dial(network, addr string, config *Config) (*Conn, error) {
 
 // LoadX509KeyPair reads and parses a public/private key pair from a pair of
 // files. The files must contain PEM encoded data.
-func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err error) {
+func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
        certPEMBlock, err := ioutil.ReadFile(certFile)
        if err != nil {
                return
index 5a0a87678e37336d238c23f222e89e1bbba05b45..616a0b3c1e8570b5d2b236f0ddf32f5ffb8d34ba 100644 (file)
@@ -101,3 +101,13 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
 
        return
 }
+
+// Subjects returns a list of the DER-encoded subjects of
+// all of the certificates in the pool. 
+func (s *CertPool) Subjects() (res [][]byte) {
+       res = make([][]byte, len(s.certs))
+       for i, c := range s.certs {
+               res[i] = c.RawSubject
+       }
+       return
+}