Commit 7b7dac5e authored by Joel Sing's avatar Joel Sing Committed by Adam Langley

crypto/tls: Add support for ECDHE-ECDSA

Add support for ECDHE-ECDSA (RFC4492), which uses an ephemeral server
key pair to perform ECDH with ECDSA signatures. Like ECDHE-RSA,
ECDHE-ECDSA also provides PFS.

R=agl
CC=golang-dev
https://golang.org/cl/7006047
parent 85a7c090
...@@ -77,5 +77,8 @@ func RegisterHash(h Hash, f func() hash.Hash) { ...@@ -77,5 +77,8 @@ func RegisterHash(h Hash, f func() hash.Hash) {
hashes[h] = f hashes[h] = f
} }
// PublicKey represents a public key using an unspecified algorithm.
type PublicKey interface{}
// PrivateKey represents a private key using an unspecified algorithm. // PrivateKey represents a private key using an unspecified algorithm.
type PrivateKey interface{} type PrivateKey interface{}
...@@ -55,8 +55,11 @@ var cipherSuites = []*cipherSuite{ ...@@ -55,8 +55,11 @@ var cipherSuites = []*cipherSuite{
// Ciphersuite order is chosen so that ECDHE comes before plain RSA // Ciphersuite order is chosen so that ECDHE comes before plain RSA
// and RC4 comes before AES (because of the Lucky13 attack). // and RC4 comes before AES (because of the Lucky13 attack).
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1}, {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, true, cipherRC4, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1}, {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, true, cipherAES, macSHA1},
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1}, {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1}, {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
...@@ -161,8 +164,16 @@ func rsaKA(version uint16) keyAgreement { ...@@ -161,8 +164,16 @@ func rsaKA(version uint16) keyAgreement {
return rsaKeyAgreement{} return rsaKeyAgreement{}
} }
func ecdheECDSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
sigType: signatureECDSA,
version: version,
}
}
func ecdheRSAKA(version uint16) keyAgreement { func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheRSAKeyAgreement{ return &ecdheKeyAgreement{
sigType: signatureRSA,
version: version, version: version,
} }
} }
...@@ -186,12 +197,15 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { ...@@ -186,12 +197,15 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
// A list of the possible cipher suite ids. Taken from // A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const ( const (
TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
) )
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"crypto/rand" "crypto/rand"
"crypto/x509" "crypto/x509"
"io" "io"
"math/big"
"strings" "strings"
"sync" "sync"
"time" "time"
...@@ -98,6 +99,12 @@ const ( ...@@ -98,6 +99,12 @@ const (
certTypeDSSSign = 2 // A certificate containing a DSA key certTypeDSSSign = 2 // A certificate containing a DSA key
certTypeRSAFixedDH = 3 // A certificate containing a static DH key certTypeRSAFixedDH = 3 // A certificate containing a static DH key
certTypeDSSFixedDH = 4 // A certificate containing a static DH key certTypeDSSFixedDH = 4 // A certificate containing a static DH key
// See RFC4492 sections 3 and 5.5.
certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
// Rest of these are reserved by the TLS spec // Rest of these are reserved by the TLS spec
) )
...@@ -120,10 +127,11 @@ type signatureAndHash struct { ...@@ -120,10 +127,11 @@ type signatureAndHash struct {
} }
// supportedSignatureAlgorithms contains the signature and hash algorithms that // supportedSignatureAlgorithms contains the signature and hash algorithms that
// the code will adverse as supported both in a TLS 1.2 ClientHello and // the code can advertise as supported both in a TLS 1.2 ClientHello and
// CertificateRequest. // CertificateRequest.
var supportedSignatureAlgorithms = []signatureAndHash{ var supportedSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA}, {hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
} }
// ConnectionState records basic TLS details about the connection. // ConnectionState records basic TLS details about the connection.
...@@ -372,7 +380,7 @@ func (c *Config) BuildNameToCertificate() { ...@@ -372,7 +380,7 @@ func (c *Config) BuildNameToCertificate() {
// A Certificate is a chain of one or more certificates, leaf first. // A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct { type Certificate struct {
Certificate [][]byte Certificate [][]byte
PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
// OCSPStaple contains an optional OCSP response which will be served // OCSPStaple contains an optional OCSP response which will be served
// to clients that request it. // to clients that request it.
OCSPStaple []byte OCSPStaple []byte
...@@ -395,6 +403,13 @@ type handshakeMessage interface { ...@@ -395,6 +403,13 @@ type handshakeMessage interface {
unmarshal([]byte) bool unmarshal([]byte) bool
} }
// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
type dsaSignature struct {
R, S *big.Int
}
type ecdsaSignature dsaSignature
var emptyConfig Config var emptyConfig Config
func defaultConfig() *Config { func defaultConfig() *Config {
......
...@@ -6,9 +6,11 @@ package tls ...@@ -6,9 +6,11 @@ package tls
import ( import (
"bytes" "bytes"
"crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
"strconv" "strconv"
...@@ -124,7 +126,10 @@ func (c *Conn) clientHandshake() error { ...@@ -124,7 +126,10 @@ func (c *Conn) clientHandshake() error {
} }
} }
if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok { switch certs[0].PublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey:
break
default:
return c.sendAlert(alertUnsupportedCertificate) return c.sendAlert(alertUnsupportedCertificate)
} }
...@@ -187,12 +192,13 @@ func (c *Conn) clientHandshake() error { ...@@ -187,12 +192,13 @@ func (c *Conn) clientHandshake() error {
finishedHash.Write(certReq.marshal()) finishedHash.Write(certReq.marshal())
// For now, we only know how to sign challenges with RSA var rsaAvail, ecdsaAvail bool
rsaAvail := false
for _, certType := range certReq.certificateTypes { for _, certType := range certReq.certificateTypes {
if certType == certTypeRSASign { switch certType {
case certTypeRSASign:
rsaAvail = true rsaAvail = true
break case certTypeECDSASign:
ecdsaAvail = true
} }
} }
...@@ -201,7 +207,7 @@ func (c *Conn) clientHandshake() error { ...@@ -201,7 +207,7 @@ func (c *Conn) clientHandshake() error {
// certReq.certificateAuthorities // certReq.certificateAuthorities
findCert: findCert:
for i, chain := range c.config.Certificates { for i, chain := range c.config.Certificates {
if !rsaAvail { if !rsaAvail && !ecdsaAvail {
continue continue
} }
...@@ -216,7 +222,10 @@ func (c *Conn) clientHandshake() error { ...@@ -216,7 +222,10 @@ func (c *Conn) clientHandshake() error {
} }
} }
if x509Cert.PublicKeyAlgorithm != x509.RSA { switch {
case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
default:
continue findCert continue findCert
} }
...@@ -271,9 +280,21 @@ func (c *Conn) clientHandshake() error { ...@@ -271,9 +280,21 @@ func (c *Conn) clientHandshake() error {
} }
if chainToSend != nil { if chainToSend != nil {
var signed []byte
certVerify := new(certificateVerifyMsg) certVerify := new(certificateVerifyMsg)
digest, hashFunc := finishedHash.hashForClientCertificate() switch key := c.config.Certificates[0].PrivateKey.(type) {
signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), hashFunc, digest) case *ecdsa.PrivateKey:
digest, _ := finishedHash.hashForClientCertificate(signatureECDSA)
r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
if err == nil {
signed, err = asn1.Marshal(ecdsaSignature{r, s})
}
case *rsa.PrivateKey:
digest, hashFunc := finishedHash.hashForClientCertificate(signatureRSA)
signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
default:
err = errors.New("unknown private key type")
}
if err != nil { if err != nil {
return c.sendAlert(alertInternalError) return c.sendAlert(alertInternalError)
} }
......
...@@ -39,16 +39,24 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config * ...@@ -39,16 +39,24 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
} }
} }
func TestHandshakeClientRC4(t *testing.T) { func TestHandshakeClientRSARC4(t *testing.T) {
var config = *testConfig var config = *testConfig
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
testClientScript(t, "RC4", rc4ClientScript, &config) testClientScript(t, "RSA-RC4", rsaRC4ClientScript, &config)
} }
func TestHandshakeClientECDHEAES(t *testing.T) { func TestHandshakeClientECDHERSAAES(t *testing.T) {
var config = *testConfig var config = *testConfig
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
testClientScript(t, "ECDHE-AES", ecdheAESClientScript, &config) testClientScript(t, "ECDHE-RSA-AES", ecdheRSAAESClientScript, &config)
}
func TestHandshakeClientECDHECDSAAES(t *testing.T) {
var config = *testConfig
config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}
config.Certificates = nil
config.BuildNameToCertificate()
testClientScript(t, "ECDHE-ECDSA-AES", ecdheECDSAAESClientScript, &config)
} }
func TestLongClientCerticiateChain(t *testing.T) { func TestLongClientCerticiateChain(t *testing.T) {
...@@ -175,7 +183,7 @@ func TestEmptyRecords(t *testing.T) { ...@@ -175,7 +183,7 @@ func TestEmptyRecords(t *testing.T) {
// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG // CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG
// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA== // HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA==
// -----END CERTIFICATE----- // -----END CERTIFICATE-----
var rc4ClientScript = [][]byte{ var rsaRC4ClientScript = [][]byte{
{ {
0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -296,7 +304,7 @@ var rc4ClientScript = [][]byte{ ...@@ -296,7 +304,7 @@ var rc4ClientScript = [][]byte{
}, },
} }
var ecdheAESClientScript = [][]byte{ var ecdheRSAAESClientScript = [][]byte{
{ {
0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -1811,265 +1819,178 @@ var clientChainCertificateScript = [][]byte{ ...@@ -1811,265 +1819,178 @@ var clientChainCertificateScript = [][]byte{
}, },
} }
// $ openssl s_server -tls1_2 -cert server.crt -key server.key \
// -cipher ECDHE-RSA-AES128-SHA -port 10443
// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc013 \
// -minversion=0x0303 -maxversion=0x0303
var clientTLS12Script = [][]byte{ var clientTLS12Script = [][]byte{
{ {
0x16, 0x03, 0x01, 0x00, 0x52, 0x01, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x4e, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x03, 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, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
0x01, 0x00, 0x00, 0x23, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x25, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
0x0d, 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, 0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x04,
0x03,
}, },
{ {
0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x03, 0x51, 0xcd, 0xe6, 0x5e, 0x4c, 0x50, 0x03, 0x03, 0x51, 0xe5, 0x78, 0x4c, 0x64,
0x36, 0x2f, 0xe1, 0x38, 0x6c, 0xff, 0x9c, 0xe2, 0x66, 0xd0, 0xee, 0x0b, 0x8b, 0xfd, 0x9b, 0xe0,
0x0f, 0xbb, 0x04, 0x6d, 0x82, 0xa6, 0x1a, 0x85, 0x54, 0x3c, 0x6e, 0x05, 0x04, 0x2f, 0x77, 0x07,
0xfa, 0x8c, 0x04, 0xb7, 0xcb, 0xcc, 0x39, 0x02, 0x8c, 0x04, 0xb9, 0xf6, 0xdd, 0xea, 0x1a, 0x7c,
0xb3, 0x24, 0xff, 0x20, 0xaa, 0x79, 0xb0, 0x04, 0xdf, 0x65, 0x39, 0x20, 0xea, 0xa2, 0xef, 0x53,
0x70, 0x39, 0x7a, 0x3b, 0xd7, 0xe0, 0x16, 0x43, 0x96, 0xf5, 0x0b, 0x8a, 0x47, 0xa0, 0x7c, 0x20,
0x63, 0xd2, 0x04, 0xc9, 0x4a, 0x49, 0x08, 0xf8, 0x53, 0x75, 0xee, 0x87, 0xb9, 0xd3, 0xe2, 0xa6,
0x1c, 0xf6, 0xba, 0x5f, 0xe2, 0x61, 0x8c, 0xa4, 0x97, 0x64, 0xb9, 0xa6, 0xcc, 0xc0, 0xe5, 0xbf,
0x3d, 0x81, 0x6a, 0x79, 0xc0, 0x13, 0x00, 0x00, 0x92, 0x1d, 0xee, 0x4d, 0xc0, 0x13, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x03, 0x03, 0xf5, 0x0b, 0x00, 0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
0x03, 0xf1, 0x00, 0x03, 0xee, 0x00, 0x03, 0xeb, 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
0x30, 0x82, 0x03, 0xe7, 0x30, 0x82, 0x02, 0xcf, 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5,
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
0xb9, 0xee, 0xd4, 0xd9, 0x55, 0xa5, 0x9e, 0xb3, 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x16, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
0x0d, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, 0x4c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x22, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
0x19, 0x46, 0x4f, 0x52, 0x20, 0x54, 0x45, 0x53, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
0x54, 0x49, 0x4e, 0x47, 0x20, 0x50, 0x55, 0x52, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
0x50, 0x4f, 0x53, 0x45, 0x53, 0x20, 0x4f, 0x4e, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e,
0x4c, 0x59, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36,
0x55, 0x04, 0x03, 0x0c, 0x1c, 0x4f, 0x70, 0x65, 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17,
0x6e, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, 0x73, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31,
0x74, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45,
0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x31, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
0x32, 0x30, 0x38, 0x31, 0x34, 0x30, 0x31, 0x34, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
0x38, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x30, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
0x31, 0x36, 0x31, 0x34, 0x30, 0x31, 0x34, 0x38, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
0x5a, 0x30, 0x64, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
0x0a, 0x0c, 0x0d, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30,
0x53, 0x4c, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70,
0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04,
0x0b, 0x0c, 0x19, 0x46, 0x4f, 0x52, 0x20, 0x54,
0x45, 0x53, 0x54, 0x49, 0x4e, 0x47, 0x20, 0x50,
0x55, 0x52, 0x50, 0x4f, 0x53, 0x45, 0x53, 0x20,
0x4f, 0x4e, 0x4c, 0x59, 0x31, 0x19, 0x30, 0x17,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x54,
0x65, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76,
0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x30,
0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
0xf3, 0x84, 0xf3, 0x92, 0x36, 0xdc, 0xb2, 0x46,
0xca, 0x66, 0x7a, 0xe5, 0x29, 0xc5, 0xf3, 0x49,
0x28, 0x22, 0xd3, 0xb9, 0xfe, 0xe0, 0xde, 0xe4,
0x38, 0xce, 0xee, 0x22, 0x1c, 0xe9, 0x91, 0x3b,
0x94, 0xd0, 0x72, 0x2f, 0x87, 0x85, 0x59, 0x4b,
0x66, 0xb1, 0xc5, 0xf5, 0x7a, 0x85, 0x5d, 0xc2,
0x0f, 0xd3, 0x2e, 0x29, 0x58, 0x36, 0xcc, 0x48,
0x6b, 0xa2, 0xa2, 0xb5, 0x26, 0xce, 0x67, 0xe2,
0x47, 0xb6, 0xdf, 0x49, 0xd2, 0x3f, 0xfa, 0xa2,
0x10, 0xb7, 0xc2, 0x97, 0x44, 0x7e, 0x87, 0x34,
0x6d, 0x6d, 0xf2, 0x8b, 0xb4, 0x55, 0x2b, 0xd6,
0x21, 0xde, 0x53, 0x4b, 0x90, 0xea, 0xfd, 0xea,
0xf9, 0x38, 0x35, 0x2b, 0xf4, 0xe6, 0x9a, 0x0e,
0xf6, 0xbb, 0x12, 0xab, 0x87, 0x21, 0xc3, 0x2f,
0xbc, 0xf4, 0x06, 0xb8, 0x8f, 0x8e, 0x10, 0x07,
0x27, 0x95, 0xe5, 0x42, 0xcb, 0xd1, 0xd5, 0x10,
0x8c, 0x92, 0xac, 0xee, 0x0f, 0xdc, 0x23, 0x48,
0x89, 0xc9, 0xc6, 0x93, 0x0c, 0x22, 0x02, 0xe7,
0x74, 0xe7, 0x25, 0x00, 0xab, 0xf8, 0x0f, 0x5c,
0x10, 0xb5, 0x85, 0x3b, 0x66, 0x94, 0xf0, 0xfb,
0x4d, 0x57, 0x06, 0x55, 0x21, 0x22, 0x25, 0xdb,
0xf3, 0xaa, 0xa9, 0x60, 0xbf, 0x4d, 0xaa, 0x79,
0xd1, 0xab, 0x92, 0x48, 0xba, 0x19, 0x8e, 0x12,
0xec, 0x68, 0xd9, 0xc6, 0xba, 0xdf, 0xec, 0x5a,
0x1c, 0xd8, 0x43, 0xfe, 0xe7, 0x52, 0xc9, 0xcf,
0x02, 0xd0, 0xc7, 0x7f, 0xc9, 0x7e, 0xb0, 0x94,
0xe3, 0x53, 0x44, 0x58, 0x0b, 0x2e, 0xfd, 0x29,
0x74, 0xb5, 0x06, 0x9b, 0x5c, 0x44, 0x8d, 0xfb,
0x32, 0x75, 0xa4, 0x3a, 0xa8, 0x67, 0x7b, 0x87,
0x32, 0x0a, 0x50, 0x8d, 0xe1, 0xa2, 0x13, 0x4a,
0x25, 0xaf, 0xe6, 0x1c, 0xb1, 0x25, 0xbf, 0xb4,
0x99, 0xa2, 0x53, 0xd3, 0xa2, 0x02, 0xbf, 0x11,
0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0x8f,
0x30, 0x81, 0x8c, 0x30, 0x0c, 0x06, 0x03, 0x55,
0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30,
0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x05,
0xe0, 0x30, 0x2c, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x1f,
0x16, 0x1d, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53,
0x4c, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61,
0x74, 0x65, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30,
0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
0x04, 0x14, 0x82, 0xbc, 0xcf, 0x00, 0x00, 0x13,
0xd1, 0xf7, 0x39, 0x25, 0x9a, 0x27, 0xe7, 0xaf,
0xd2, 0xef, 0x20, 0x1b, 0x6e, 0xac, 0x30, 0x1f,
0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0x36, 0xc3, 0x6c, 0x88, 0xe7,
0x95, 0xfe, 0xb0, 0xbd, 0xec, 0xce, 0x3e, 0x3d,
0x86, 0xab, 0x21, 0x81, 0x87, 0xda, 0xda, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
0x01, 0x01, 0x00, 0xa9, 0xbd, 0x4d, 0x57, 0x40, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3,
0x74, 0xfe, 0x96, 0xe9, 0x2b, 0xd6, 0x78, 0xfd, 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52,
0xb3, 0x63, 0xcc, 0xf4, 0x0b, 0x4d, 0x12, 0xca, 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80,
0x5a, 0x74, 0x8d, 0x9b, 0xf2, 0x61, 0xe6, 0xfd, 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61,
0x06, 0x11, 0x43, 0x84, 0xfc, 0x17, 0xa0, 0xec, 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe,
0x63, 0x63, 0x36, 0xb9, 0x9e, 0x36, 0x6a, 0xb1, 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a,
0x02, 0x5a, 0x6a, 0x5b, 0x3f, 0x6a, 0xa1, 0xea, 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff,
0x05, 0x65, 0xac, 0x7e, 0x40, 0x1a, 0x48, 0x65, 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f,
0x88, 0xd1, 0x39, 0x4d, 0xd3, 0x4b, 0x77, 0xe9, 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03,
0xc8, 0xbb, 0x2b, 0x9e, 0x5a, 0xf4, 0x08, 0x34, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
0x39, 0x47, 0xb9, 0x02, 0x08, 0x31, 0x9a, 0xf1, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
0xd9, 0x17, 0xc5, 0xe9, 0xa6, 0xa5, 0x96, 0x4b, 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a,
0x6d, 0x40, 0xa9, 0x5b, 0x65, 0x28, 0xcb, 0xcb, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22,
0x00, 0x03, 0x82, 0x63, 0x37, 0xd3, 0xad, 0xb1, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b,
0x96, 0x3b, 0x76, 0xf5, 0x17, 0x16, 0x02, 0x7b, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
0xbd, 0x53, 0x53, 0x46, 0x72, 0x34, 0xd6, 0x08, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97,
0x64, 0x9d, 0xbb, 0x43, 0xfb, 0x64, 0xb1, 0x49, 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba,
0x07, 0x77, 0x09, 0x61, 0x7a, 0x42, 0x17, 0x11, 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc,
0x30, 0x0c, 0xd9, 0x27, 0x5c, 0xf5, 0x71, 0xb6, 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
0xf0, 0x18, 0x30, 0xf3, 0x7e, 0xf1, 0x85, 0x3f, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x32, 0x7e, 0x4a, 0xaf, 0xb3, 0x10, 0xf7, 0x6c, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
0xc6, 0x85, 0x4b, 0x2d, 0x27, 0xad, 0x0a, 0x20, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
0x5c, 0xfb, 0x8d, 0x19, 0x70, 0x34, 0xb9, 0x75, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
0x5f, 0x7c, 0x87, 0xd5, 0xc3, 0xec, 0x93, 0x13, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
0x41, 0xfc, 0x73, 0x03, 0xb9, 0x8d, 0x1a, 0xfe, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
0xf7, 0x26, 0x86, 0x49, 0x03, 0xa9, 0xc5, 0x82, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
0x3f, 0x80, 0x0d, 0x29, 0x49, 0xb1, 0x8f, 0xed, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
0x24, 0x1b, 0xfe, 0xcf, 0x58, 0x90, 0x46, 0xe7, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1,
0xa8, 0x87, 0xd4, 0x1e, 0x79, 0xef, 0x99, 0x6d, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30,
0x18, 0x9f, 0x3e, 0x8b, 0x82, 0x07, 0xc1, 0x43, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
0xc7, 0xe0, 0x25, 0xb6, 0xf1, 0xd3, 0x00, 0xd7, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
0x40, 0xab, 0x4b, 0x7f, 0x2b, 0x7a, 0x3e, 0xa6, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x99, 0x4c, 0x54, 0x16, 0x03, 0x03, 0x01, 0x4d, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85,
0x0c, 0x00, 0x01, 0x49, 0x03, 0x00, 0x17, 0x41, 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4,
0x04, 0x8f, 0x92, 0xa0, 0x20, 0xdc, 0x70, 0xce, 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74,
0xaf, 0x50, 0x44, 0xa8, 0x53, 0x15, 0xbf, 0x74, 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf,
0x0c, 0xed, 0x60, 0x26, 0xac, 0xb0, 0x07, 0x17, 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46,
0x59, 0x02, 0x6d, 0x9f, 0x45, 0x57, 0x3b, 0x9c, 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b,
0x67, 0xae, 0xb8, 0xa6, 0x70, 0xa9, 0x03, 0xb4, 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92,
0x37, 0x7b, 0xe4, 0x2f, 0x7c, 0x42, 0x4f, 0xaa, 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
0x9a, 0x5d, 0x10, 0x65, 0xc1, 0xa5, 0x33, 0xff, 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
0xc5, 0xdf, 0x24, 0xdb, 0x8f, 0xe2, 0x14, 0xee, 0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
0x00, 0x04, 0x01, 0x01, 0x00, 0x76, 0xcf, 0xe6, 0x03, 0x00, 0x17, 0x41, 0x04, 0x39, 0xe9, 0x59,
0x47, 0xcf, 0xc1, 0x58, 0xf5, 0x5d, 0x3a, 0x0b, 0x24, 0x76, 0xf0, 0x1a, 0xd6, 0x21, 0xa5, 0xbc,
0xd5, 0x4e, 0xb1, 0x08, 0xa6, 0x03, 0x8b, 0xa3, 0x28, 0xb9, 0xd5, 0x3d, 0xf7, 0xf3, 0xbe, 0x09,
0x7b, 0x9c, 0xa2, 0x3b, 0x99, 0x7e, 0x42, 0x0d, 0xff, 0xc1, 0x79, 0x33, 0x82, 0xf8, 0xe1, 0x5f,
0x38, 0x6e, 0x9a, 0x5e, 0xf7, 0x45, 0x7f, 0xf3, 0x1c, 0x34, 0x96, 0x3a, 0x10, 0xf2, 0x2c, 0x69,
0x51, 0xa2, 0xe6, 0xae, 0x1c, 0x55, 0x2a, 0x58, 0xab, 0x57, 0xf6, 0x20, 0xb6, 0x59, 0x1f, 0x8c,
0x13, 0x55, 0xa9, 0x93, 0xac, 0x6a, 0x1e, 0xd6, 0x3e, 0xa2, 0xac, 0x4d, 0xf2, 0x10, 0x58, 0x0b,
0xd9, 0x98, 0x89, 0x93, 0x16, 0x8f, 0xab, 0xc5, 0x61, 0x27, 0x6c, 0x47, 0xa0, 0x52, 0xc7, 0xe6,
0x65, 0x65, 0x62, 0x68, 0xd8, 0xbf, 0xbd, 0x4e, 0x36, 0xfd, 0xb1, 0xa2, 0x49, 0x04, 0x01, 0x00,
0x1a, 0x17, 0x24, 0x9c, 0x3c, 0x56, 0xf5, 0x8f, 0x40, 0x99, 0x7e, 0xf9, 0xed, 0x8b, 0x62, 0x82,
0xda, 0x6e, 0x03, 0xe7, 0xe9, 0xce, 0xe5, 0xb1, 0x00, 0xde, 0x5f, 0x2f, 0xb9, 0xf9, 0x9d, 0xa1,
0x68, 0xd8, 0x88, 0xdb, 0xde, 0xfe, 0x98, 0xbe, 0xb0, 0x14, 0x05, 0xc1, 0xdd, 0xa3, 0xb9, 0x08,
0x9d, 0x1f, 0x86, 0xbf, 0x36, 0xe5, 0xe9, 0x77, 0xa5, 0x36, 0xb6, 0xfe, 0x8a, 0x5b, 0x2d, 0x6e,
0xc3, 0xa6, 0xa3, 0x30, 0x60, 0x9f, 0x36, 0x65, 0xd8, 0x5a, 0x5c, 0x89, 0x84, 0x85, 0x56, 0x01,
0x4c, 0xe5, 0xb6, 0x3f, 0xf8, 0x15, 0x76, 0xac, 0xaf, 0x43, 0xd3, 0x0f, 0x85, 0xd0, 0xb2, 0x35,
0x4f, 0xb5, 0x8a, 0x98, 0xe3, 0xc2, 0xbd, 0x13, 0x3d, 0x1d, 0xd6, 0x67, 0x52, 0x48, 0xe8, 0x82,
0xff, 0x59, 0xfd, 0x22, 0xbf, 0xb3, 0x02, 0xab, 0x47, 0xbb, 0x2a, 0x54, 0x4a, 0x55, 0xcd, 0x10,
0xf1, 0x82, 0xff, 0x4c, 0x41, 0x81, 0x15, 0xa5, 0x54, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
0xc7, 0x56, 0x93, 0xc3, 0xb0, 0xd2, 0x70, 0x84, 0x00, 0x00,
0xb6, 0x27, 0x43, 0x47, 0x38, 0x3a, 0xcf, 0x20,
0xa4, 0x97, 0x61, 0xc7, 0xf9, 0xb2, 0x01, 0xea,
0x83, 0x72, 0x00, 0x74, 0x3e, 0x41, 0xd0, 0x24,
0x32, 0xf7, 0xe1, 0x68, 0xae, 0x06, 0xcb, 0x70,
0x06, 0x3a, 0x3a, 0xd3, 0x97, 0x7e, 0xaa, 0x27,
0xb7, 0xcc, 0xd3, 0x7f, 0xb2, 0x07, 0x9e, 0x85,
0x16, 0x25, 0x28, 0xee, 0xc7, 0x29, 0x09, 0x56,
0x94, 0x6c, 0x7e, 0xe4, 0x61, 0x7b, 0xc2, 0xd5,
0x03, 0x46, 0x71, 0x69, 0xc0, 0x90, 0x0e, 0x58,
0xc6, 0xef, 0xf5, 0x23, 0x03, 0x42, 0x92, 0x1a,
0x2f, 0x4b, 0x0a, 0x5d, 0x74, 0x71, 0x28, 0x5a,
0x83, 0xf2, 0x00, 0x79, 0x65, 0x89, 0x61, 0x87,
0x31, 0xf0, 0x09, 0x89, 0x6a, 0xc4, 0x48, 0xee,
0x78, 0xf1, 0x65, 0x3f, 0xe1, 0x16, 0x03, 0x03,
0x00, 0x5a, 0x0d, 0x00, 0x00, 0x52, 0x03, 0x01,
0x02, 0x40, 0x00, 0x20, 0x06, 0x01, 0x06, 0x02,
0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03,
0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01,
0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
0x02, 0x03, 0x01, 0x01, 0x00, 0x2a, 0x00, 0x28,
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,
0x0e, 0x00, 0x00, 0x00,
}, },
{ {
0x16, 0x03, 0x03, 0x00, 0x07, 0x0b, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
0x46, 0x10, 0x00, 0x00, 0x42, 0x41, 0x04, 0x1e, 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
0x18, 0x37, 0xef, 0x0d, 0x19, 0x51, 0x88, 0x35, 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
0x75, 0x71, 0xb5, 0xe5, 0x54, 0x5b, 0x12, 0x2e, 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
0x8f, 0x09, 0x67, 0xfd, 0xa7, 0x24, 0x20, 0x3e, 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
0xb2, 0x56, 0x1c, 0xce, 0x97, 0x28, 0x5e, 0xf8, 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
0x2b, 0x2d, 0x4f, 0x9e, 0xf1, 0x07, 0x9f, 0x6c, 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
0x4b, 0x5b, 0x83, 0x56, 0xe2, 0x32, 0x42, 0xe9, 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
0x58, 0xb6, 0xd7, 0x49, 0xa6, 0xb5, 0x68, 0x1a, 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x03, 0x00, 0x01,
0x41, 0x03, 0x56, 0x6b, 0xdc, 0x5a, 0x89, 0x14, 0x01, 0x16, 0x03, 0x03, 0x00, 0x40, 0x00, 0x00,
0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xb8, 0x47, 0xfb, 0xd2, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xcb,
0x62, 0x74, 0x63, 0x54, 0xb8, 0x03, 0x7b, 0xb9, 0x97, 0x41, 0x63, 0x39, 0xeb, 0xda, 0x04, 0x39,
0x05, 0x87, 0x60, 0x6f, 0xb9, 0xfc, 0x79, 0x96, 0xfb, 0x67, 0x1d, 0x6d, 0xf8, 0x58, 0xd1, 0x22,
0xce, 0xf0, 0x84, 0x77, 0x23, 0x1b, 0x44, 0x3f, 0x35, 0xe3, 0xc3, 0x9d, 0xfc, 0x4e, 0xcc, 0x71,
0x33, 0xe8, 0x71, 0x97, 0x9d, 0xd3, 0x7d, 0x43, 0x93, 0x78, 0x64, 0x39, 0x04, 0xa0, 0xa9, 0x41,
0x40, 0xd3, 0x95, 0x65, 0x1f, 0x2c, 0x30, 0xfd, 0xcf, 0x4c, 0xd6, 0x34, 0xad, 0x5c, 0xc9, 0x7a,
0x7f, 0xac, 0x44, 0xb1, 0x1d, 0x77, 0x52, 0x01,
}, },
{ {
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x40, 0x64, 0x09, 0x6c, 0x06, 0x5a, 0x03, 0x00, 0x40, 0x55, 0x75, 0x8a, 0x57, 0xb4,
0x01, 0x24, 0x10, 0xd9, 0x92, 0x66, 0xe6, 0x28, 0x53, 0xa2, 0x8f, 0xbf, 0xd3, 0x79, 0x72, 0x1e,
0x43, 0x2f, 0xba, 0x0b, 0x17, 0x61, 0x55, 0x42, 0x94, 0x53, 0xb3, 0x03, 0x9d, 0x4d, 0x8a, 0x1f,
0x9d, 0xc3, 0x59, 0xba, 0x57, 0x19, 0x1b, 0x74, 0xbd, 0x25, 0x79, 0x69, 0x61, 0x65, 0xd7, 0x26,
0x22, 0x40, 0xc7, 0x13, 0x95, 0x83, 0xe6, 0xf3, 0xad, 0xa6, 0x0e, 0x89, 0x83, 0xc0, 0xbe, 0x46,
0x11, 0x62, 0xe6, 0xde, 0xfc, 0xf3, 0x1a, 0xd1, 0x51, 0xe4, 0x38, 0x7b, 0x65, 0x74, 0x6d, 0x24,
0x3d, 0xce, 0xd1, 0xf9, 0xeb, 0x2e, 0x13, 0x39, 0xff, 0xd4, 0x9f, 0xcb, 0xfc, 0xd7, 0x03, 0xaa,
0xa6, 0xdb, 0x04, 0x79, 0xaa, 0x2d, 0xe1, 0xa4, 0x7b, 0x8e, 0x30, 0x09, 0xdb, 0xaa, 0x9d, 0xad,
0xd0, 0xf9, 0x36, 0xcd, 0x56, 0xcf,
}, },
{ {
0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01, 0x46,
0xcb, 0x65, 0xc1, 0xac, 0x94, 0xc5, 0x1d, 0x4d, 0xa8, 0xdd, 0x62, 0x73, 0x67, 0x99, 0x01, 0x42,
0xc5, 0x1e, 0xd4, 0x17, 0xe3, 0x83, 0xac, 0x14, 0xb2, 0x9e, 0x22, 0x18, 0xf5, 0x8f, 0x10, 0x97,
0x80, 0x92, 0x2d, 0x5b, 0x42, 0x19, 0xcb, 0x51, 0xde, 0x58, 0x24, 0x34, 0x36, 0xa2, 0x5d, 0xf4,
0xc9, 0x48, 0xdf, 0xf6, 0x27, 0x15, 0x03, 0x03, 0x96, 0x2a, 0xed, 0x6c, 0x06, 0x15, 0x03, 0x03,
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf7, 0xc2, 0xed, 0x1a, 0x88, 0xb6, 0x00, 0x00, 0x9f, 0x7a, 0x9f, 0xab, 0xf5, 0x4e,
0xb8, 0x26, 0x04, 0x31, 0x89, 0xab, 0x29, 0x34, 0x1c, 0x4e, 0xf4, 0xcb, 0x1a, 0x39, 0xae, 0x21,
0xce, 0x84, 0x81, 0x33, 0x64, 0x8e, 0x53, 0xa3, 0x85, 0x39, 0xc4, 0x51, 0xac, 0x14, 0xde, 0xa0,
0xaf, 0x8b, 0x5a, 0x50, 0x43, 0xab, 0x77, 0x77, 0xe7, 0x70, 0x7c, 0x6a, 0x53, 0x54, 0x19, 0xbc,
0xa3, 0xc7, 0x2f, 0x32,
}, },
} }
...@@ -2358,3 +2279,208 @@ var testClientChainCertificate = fromHex( ...@@ -2358,3 +2279,208 @@ var testClientChainCertificate = fromHex(
"77796d5a695731673d3d0a2d2d2d2d2d454e4420" + "77796d5a695731673d3d0a2d2d2d2d2d454e4420" +
"43455254494649434154452d2d2d2d2d0a", "43455254494649434154452d2d2d2d2d0a",
) )
// Script of interaction with openssl implementation:
//
// openssl s_server -cipher ECDHE-ECDSA-AES128-SHA \
// -key server.key -cert server.crt -port 10443
//
// The values for this test are obtained by building and running in client mode:
// % go test -test.run "TestRunClient" -connect -ciphersuites=0xc009
// The recorded bytes are written to stdout.
//
// The server private key is:
//
// -----BEGIN EC PARAMETERS-----
// BgUrgQQAIw==
// -----END EC PARAMETERS-----
// -----BEGIN EC PRIVATE KEY-----
// MIHcAgEBBEIBmIPpCa0Kyeo9M/nq5mHxeFIGlw+MqakWcvHu3Keo7xK9ZWG7JG3a
// XfS01efjqSZJvF2DoL+Sly4A5iBn0Me9mdegBwYFK4EEACOhgYkDgYYABADEoe2+
// mPkLSHM2fsMWVhEi8j1TwztNIT3Na3Xm9rDcmt8mwbyyh/ByMnyzZC8ckLzqaCMQ
// fv7jJcBIOmngKG3TNwDvBGLdDaCccGKD2IHTZDGqnpcxvZawaMCbI952ZD8aXH/p
// Eg5YWLZfcN2b2OrV1/XVzLm2nzBmW2aaIOIn5b/+Ow==
// -----END EC PRIVATE KEY-----
//
// and certificate is:
//
// -----BEGIN CERTIFICATE-----
// MIICADCCAWICCQC4vy1HoNLr9DAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
// EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
// eSBMdGQwHhcNMTIxMTIyMTUwNjMyWhcNMjIxMTIwMTUwNjMyWjBFMQswCQYDVQQG
// EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
// Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAxKHtvpj5C0hz
// Nn7DFlYRIvI9U8M7TSE9zWt15vaw3JrfJsG8sofwcjJ8s2QvHJC86mgjEH7+4yXA
// SDpp4Cht0zcA7wRi3Q2gnHBig9iB02Qxqp6XMb2WsGjAmyPedmQ/Glx/6RIOWFi2
// X3Ddm9jq1df11cy5tp8wZltmmiDiJ+W//jswCQYHKoZIzj0EAQOBjAAwgYgCQgGI
// ok/r4kXFSH0brPXtmJ2uR3DAXhu2L73xtk23YUDTEaLO7gt+kn7/dp3DO36lP876
// EOJZ7EctfKzaTpcOFaBv0AJCAU38vmcTnC0FDr0/o4wlwTMTgw2UBrvUN3r27HrJ
// hi7d1xFpf4V8Vt77MXgr5Md4Da7Lvp5ONiQxe2oPOZUSB48q
// -----END CERTIFICATE-----
var ecdheECDSAAESClientScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
0x46, 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, 0x02, 0xc0, 0x09,
0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
},
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x01, 0x50, 0xd7, 0x19, 0xc9, 0x03,
0xc2, 0x3a, 0xc6, 0x1f, 0x0a, 0x84, 0x9e, 0xd7,
0xf4, 0x7e, 0x07, 0x6d, 0xa8, 0xe4, 0xa9, 0x4f,
0x22, 0x50, 0xa2, 0x19, 0x24, 0x44, 0x42, 0x65,
0xaa, 0xba, 0x3a, 0x20, 0x90, 0x70, 0xb7, 0xe5,
0x57, 0xed, 0xb1, 0xb1, 0x43, 0x4b, 0xa1, 0x4e,
0xee, 0x7a, 0x5b, 0x88, 0xf6, 0xa6, 0x73, 0x3b,
0xcb, 0xa7, 0xbd, 0x57, 0x50, 0xf2, 0x72, 0x8c,
0xbc, 0x45, 0x73, 0xaa, 0xc0, 0x09, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x01, 0x02, 0x0e, 0x0b, 0x00,
0x02, 0x0a, 0x00, 0x02, 0x07, 0x00, 0x02, 0x04,
0x30, 0x82, 0x02, 0x00, 0x30, 0x82, 0x01, 0x62,
0x02, 0x09, 0x00, 0xb8, 0xbf, 0x2d, 0x47, 0xa0,
0xd2, 0xeb, 0xf4, 0x30, 0x09, 0x06, 0x07, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, 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, 0x32, 0x31, 0x31, 0x32, 0x32, 0x31,
0x35, 0x30, 0x36, 0x33, 0x32, 0x5a, 0x17, 0x0d,
0x32, 0x32, 0x31, 0x31, 0x32, 0x30, 0x31, 0x35,
0x30, 0x36, 0x33, 0x32, 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, 0x9b, 0x30,
0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
0x23, 0x03, 0x81, 0x86, 0x00, 0x04, 0x00, 0xc4,
0xa1, 0xed, 0xbe, 0x98, 0xf9, 0x0b, 0x48, 0x73,
0x36, 0x7e, 0xc3, 0x16, 0x56, 0x11, 0x22, 0xf2,
0x3d, 0x53, 0xc3, 0x3b, 0x4d, 0x21, 0x3d, 0xcd,
0x6b, 0x75, 0xe6, 0xf6, 0xb0, 0xdc, 0x9a, 0xdf,
0x26, 0xc1, 0xbc, 0xb2, 0x87, 0xf0, 0x72, 0x32,
0x7c, 0xb3, 0x64, 0x2f, 0x1c, 0x90, 0xbc, 0xea,
0x68, 0x23, 0x10, 0x7e, 0xfe, 0xe3, 0x25, 0xc0,
0x48, 0x3a, 0x69, 0xe0, 0x28, 0x6d, 0xd3, 0x37,
0x00, 0xef, 0x04, 0x62, 0xdd, 0x0d, 0xa0, 0x9c,
0x70, 0x62, 0x83, 0xd8, 0x81, 0xd3, 0x64, 0x31,
0xaa, 0x9e, 0x97, 0x31, 0xbd, 0x96, 0xb0, 0x68,
0xc0, 0x9b, 0x23, 0xde, 0x76, 0x64, 0x3f, 0x1a,
0x5c, 0x7f, 0xe9, 0x12, 0x0e, 0x58, 0x58, 0xb6,
0x5f, 0x70, 0xdd, 0x9b, 0xd8, 0xea, 0xd5, 0xd7,
0xf5, 0xd5, 0xcc, 0xb9, 0xb6, 0x9f, 0x30, 0x66,
0x5b, 0x66, 0x9a, 0x20, 0xe2, 0x27, 0xe5, 0xbf,
0xfe, 0x3b, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x04, 0x01, 0x03, 0x81, 0x8c,
0x00, 0x30, 0x81, 0x88, 0x02, 0x42, 0x01, 0x88,
0xa2, 0x4f, 0xeb, 0xe2, 0x45, 0xc5, 0x48, 0x7d,
0x1b, 0xac, 0xf5, 0xed, 0x98, 0x9d, 0xae, 0x47,
0x70, 0xc0, 0x5e, 0x1b, 0xb6, 0x2f, 0xbd, 0xf1,
0xb6, 0x4d, 0xb7, 0x61, 0x40, 0xd3, 0x11, 0xa2,
0xce, 0xee, 0x0b, 0x7e, 0x92, 0x7e, 0xff, 0x76,
0x9d, 0xc3, 0x3b, 0x7e, 0xa5, 0x3f, 0xce, 0xfa,
0x10, 0xe2, 0x59, 0xec, 0x47, 0x2d, 0x7c, 0xac,
0xda, 0x4e, 0x97, 0x0e, 0x15, 0xa0, 0x6f, 0xd0,
0x02, 0x42, 0x01, 0x4d, 0xfc, 0xbe, 0x67, 0x13,
0x9c, 0x2d, 0x05, 0x0e, 0xbd, 0x3f, 0xa3, 0x8c,
0x25, 0xc1, 0x33, 0x13, 0x83, 0x0d, 0x94, 0x06,
0xbb, 0xd4, 0x37, 0x7a, 0xf6, 0xec, 0x7a, 0xc9,
0x86, 0x2e, 0xdd, 0xd7, 0x11, 0x69, 0x7f, 0x85,
0x7c, 0x56, 0xde, 0xfb, 0x31, 0x78, 0x2b, 0xe4,
0xc7, 0x78, 0x0d, 0xae, 0xcb, 0xbe, 0x9e, 0x4e,
0x36, 0x24, 0x31, 0x7b, 0x6a, 0x0f, 0x39, 0x95,
0x12, 0x07, 0x8f, 0x2a, 0x16, 0x03, 0x01, 0x00,
0xd6, 0x0c, 0x00, 0x00, 0xd2, 0x03, 0x00, 0x17,
0x41, 0x04, 0x33, 0xed, 0xe1, 0x10, 0x3d, 0xe2,
0xb0, 0x81, 0x5e, 0x01, 0x1b, 0x00, 0x4a, 0x7d,
0xdc, 0xc5, 0x78, 0x02, 0xb1, 0x9a, 0x78, 0x92,
0x34, 0xd9, 0x23, 0xcc, 0x01, 0xfb, 0x0c, 0x49,
0x1c, 0x4a, 0x59, 0x8a, 0x80, 0x1b, 0x34, 0xf0,
0xe8, 0x87, 0x1b, 0x7c, 0xfb, 0x72, 0xf5, 0xea,
0xf9, 0xf3, 0xff, 0xa6, 0x3e, 0x4e, 0xac, 0xbc,
0xee, 0x14, 0x2b, 0x87, 0xd4, 0x0b, 0xda, 0x19,
0x60, 0x2b, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02,
0x42, 0x01, 0x75, 0x46, 0x4f, 0x97, 0x9f, 0xc5,
0xf9, 0x4c, 0x38, 0xcf, 0x3b, 0x37, 0x1a, 0x6b,
0x53, 0xfc, 0x05, 0x73, 0x7d, 0x98, 0x2c, 0x5b,
0x76, 0xd4, 0x37, 0x1f, 0x50, 0x6d, 0xad, 0xc6,
0x0f, 0x8f, 0x7b, 0xcc, 0x60, 0x8e, 0x04, 0x00,
0x21, 0x80, 0xa8, 0xa5, 0x98, 0xf2, 0x42, 0xf2,
0xc3, 0xf6, 0x44, 0x50, 0xc4, 0x7a, 0xae, 0x6f,
0x74, 0xa0, 0x7f, 0x07, 0x7a, 0x0b, 0xbb, 0x41,
0x9e, 0x3c, 0x0b, 0x02, 0x42, 0x01, 0xbe, 0x64,
0xaa, 0x12, 0x03, 0xfb, 0xd8, 0x4f, 0x93, 0xf9,
0x92, 0x54, 0x0d, 0x9c, 0x9d, 0x53, 0x88, 0x19,
0x69, 0x94, 0xfc, 0xd6, 0xf7, 0x60, 0xcf, 0x70,
0x64, 0x15, 0x1b, 0x02, 0x22, 0x56, 0xb0, 0x2c,
0xb1, 0x72, 0x4c, 0x9e, 0x7b, 0xf0, 0x53, 0x97,
0x43, 0xac, 0x11, 0x62, 0xe5, 0x5a, 0xf1, 0x7e,
0x87, 0x8f, 0x5c, 0x43, 0x1d, 0xae, 0x56, 0x28,
0xdb, 0x76, 0x15, 0xd8, 0x1c, 0x73, 0xce, 0x16,
0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
},
{
0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01,
0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x1a, 0x45,
0x92, 0x3b, 0xac, 0x8d, 0x91, 0x89, 0xd3, 0x2c,
0xf4, 0x3c, 0x5f, 0x70, 0xf1, 0x79, 0xa5, 0x6a,
0xcf, 0x97, 0x8f, 0x3f, 0x73, 0x08, 0xca, 0x3f,
0x55, 0xb0, 0x28, 0xd1, 0x6f, 0xcd, 0x9b, 0xca,
0xb6, 0xb7, 0xd0, 0xa5, 0x21, 0x5b, 0x08, 0xf8,
0x42, 0xe2, 0xdf, 0x25, 0x6a, 0x16,
},
{
0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
0x01, 0x00, 0x30, 0x30, 0x83, 0xb6, 0x51, 0x8a,
0x85, 0x4a, 0xee, 0xe4, 0xb6, 0xae, 0xf3, 0xc1,
0xdc, 0xd2, 0x04, 0xb3, 0xd0, 0x25, 0x47, 0x5f,
0xac, 0x83, 0xa3, 0x7d, 0xcf, 0x47, 0x92, 0xed,
0x92, 0x6c, 0xd1, 0x6e, 0xfd, 0x63, 0xf5, 0x2d,
0x89, 0xd8, 0x04, 0x8c, 0x62, 0x71, 0xae, 0x5e,
0x32, 0x48, 0xf8,
},
{
0x17, 0x03, 0x01, 0x00, 0x20, 0xcf, 0x5e, 0xba,
0xf4, 0x47, 0x32, 0x35, 0x9b, 0x85, 0xdc, 0xb3,
0xff, 0x77, 0x90, 0xd9, 0x2b, 0xbd, 0x59, 0x2a,
0x33, 0xe4, 0x6e, 0x9b, 0xfc, 0x1c, 0x73, 0x3f,
0x5e, 0x1e, 0xe3, 0xa4, 0xc2, 0x17, 0x03, 0x01,
0x00, 0x20, 0x05, 0xdf, 0x2d, 0x9b, 0x29, 0x7f,
0x97, 0xcd, 0x49, 0x04, 0x53, 0x22, 0x1a, 0xa1,
0xa1, 0xe6, 0x38, 0x3a, 0x56, 0x37, 0x1f, 0xd8,
0x3a, 0x12, 0x2c, 0xf0, 0xeb, 0x61, 0x35, 0x76,
0xe5, 0xf0, 0x15, 0x03, 0x01, 0x00, 0x20, 0xa5,
0x56, 0xb5, 0x49, 0x4b, 0xc2, 0xd4, 0x4c, 0xf6,
0x95, 0x15, 0x7d, 0x41, 0x1d, 0x5c, 0x00, 0x0e,
0x20, 0xb1, 0x0a, 0xbc, 0xc9, 0x2a, 0x09, 0x17,
0xb4, 0xaa, 0x1c, 0x79, 0xda, 0x79, 0x27,
},
}
...@@ -5,9 +5,12 @@ ...@@ -5,9 +5,12 @@
package tls package tls
import ( import (
"crypto"
"crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
) )
...@@ -305,7 +308,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -305,7 +308,10 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if config.ClientAuth >= RequestClientCert { if config.ClientAuth >= RequestClientCert {
// Request a client certificate // Request a client certificate
certReq := new(certificateRequestMsg) certReq := new(certificateRequestMsg)
certReq.certificateTypes = []byte{certTypeRSASign} certReq.certificateTypes = []byte{
byte(certTypeRSASign),
byte(certTypeECDSASign),
}
if c.vers >= VersionTLS12 { if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms certReq.signatureAndHashes = supportedSignatureAlgorithms
...@@ -327,7 +333,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -327,7 +333,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.finishedHash.Write(helloDone.marshal()) hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal()) c.writeRecord(recordTypeHandshake, helloDone.marshal())
var pub *rsa.PublicKey // public key for client auth, if any var pub crypto.PublicKey // public key for client auth, if any
msg, err := c.readHandshake() msg, err := c.readHandshake()
if err != nil { if err != nil {
...@@ -372,7 +378,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -372,7 +378,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// If we received a client cert in response to our certificate request message, // If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the // the client will send us a certificateVerifyMsg immediately after the
// clientKeyExchangeMsg. This message is a MD5SHA1 digest of all preceding // clientKeyExchangeMsg. This message is a digest of all preceding
// handshake-layer messages that is signed using the private key corresponding // handshake-layer messages that is signed using the private key corresponding
// to the client's certificate. This allows us to verify that the client is in // to the client's certificate. This allows us to verify that the client is in
// possession of the private key of the certificate. // possession of the private key of the certificate.
...@@ -386,8 +392,25 @@ func (hs *serverHandshakeState) doFullHandshake() error { ...@@ -386,8 +392,25 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return c.sendAlert(alertUnexpectedMessage) return c.sendAlert(alertUnexpectedMessage)
} }
digest, hashFunc := hs.finishedHash.hashForClientCertificate() switch key := pub.(type) {
err = rsa.VerifyPKCS1v15(pub, hashFunc, digest, certVerify.signature) case *ecdsa.PublicKey:
ecdsaSig := new(ecdsaSignature)
if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
break
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
err = errors.New("ECDSA signature contained zero or negative values")
break
}
digest, _ := hs.finishedHash.hashForClientCertificate(signatureECDSA)
if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
err = errors.New("ECDSA verification failure")
break
}
case *rsa.PublicKey:
digest, hashFunc := hs.finishedHash.hashForClientCertificate(signatureRSA)
err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
}
if err != nil { if err != nil {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error()) return errors.New("could not validate signature of connection nonces: " + err.Error())
...@@ -507,7 +530,7 @@ func (hs *serverHandshakeState) sendFinished() error { ...@@ -507,7 +530,7 @@ func (hs *serverHandshakeState) sendFinished() error {
// processCertsFromClient takes a chain of client certificates either from a // processCertsFromClient takes a chain of client certificates either from a
// Certificates message or from a sessionState and verifies them. It returns // Certificates message or from a sessionState and verifies them. It returns
// the public key of the leaf certificate. // the public key of the leaf certificate.
func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) { func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
c := hs.c c := hs.c
hs.certsFromClient = certificates hs.certsFromClient = certificates
...@@ -554,8 +577,11 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (* ...@@ -554,8 +577,11 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*
} }
if len(certs) > 0 { if len(certs) > 0 {
pub, ok := certs[0].PublicKey.(*rsa.PublicKey) var pub crypto.PublicKey
if !ok { switch key := certs[0].PublicKey.(type) {
case *ecdsa.PublicKey, *rsa.PublicKey:
pub = key
default:
return nil, c.sendAlert(alertUnsupportedCertificate) return nil, c.sendAlert(alertUnsupportedCertificate)
} }
c.peerCertificates = certs c.peerCertificates = certs
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -6,12 +6,14 @@ package tls ...@@ -6,12 +6,14 @@ package tls
import ( import (
"crypto" "crypto"
"crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/md5" "crypto/md5"
"crypto/rsa" "crypto/rsa"
"crypto/sha1" "crypto/sha1"
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/asn1"
"errors" "errors"
"io" "io"
"math/big" "math/big"
...@@ -83,6 +85,15 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello ...@@ -83,6 +85,15 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return preMasterSecret, ckx, nil return preMasterSecret, ckx, nil
} }
// sha1Hash calculates a SHA1 hash over the given byte slices.
func sha1Hash(slices [][]byte) []byte {
hsha1 := sha1.New()
for _, slice := range slices {
hsha1.Write(slice)
}
return hsha1.Sum(nil)
}
// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
// concatenation of an MD5 and SHA1 hash. // concatenation of an MD5 and SHA1 hash.
func md5SHA1Hash(slices [][]byte) []byte { func md5SHA1Hash(slices [][]byte) []byte {
...@@ -92,12 +103,7 @@ func md5SHA1Hash(slices [][]byte) []byte { ...@@ -92,12 +103,7 @@ func md5SHA1Hash(slices [][]byte) []byte {
hmd5.Write(slice) hmd5.Write(slice)
} }
copy(md5sha1, hmd5.Sum(nil)) copy(md5sha1, hmd5.Sum(nil))
copy(md5sha1[md5.Size:], sha1Hash(slices))
hsha1 := sha1.New()
for _, slice := range slices {
hsha1.Write(slice)
}
copy(md5sha1[md5.Size:], hsha1.Sum(nil))
return md5sha1 return md5sha1
} }
...@@ -112,24 +118,29 @@ func sha256Hash(slices [][]byte) []byte { ...@@ -112,24 +118,29 @@ func sha256Hash(slices [][]byte) []byte {
// hashForServerKeyExchange hashes the given slices and returns their digest // hashForServerKeyExchange hashes the given slices and returns their digest
// and the identifier of the hash function used. // and the identifier of the hash function used.
func hashForServerKeyExchange(version uint16, slices ...[]byte) ([]byte, crypto.Hash) { func hashForServerKeyExchange(sigType uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash) {
if version >= VersionTLS12 { if version >= VersionTLS12 {
return sha256Hash(slices), crypto.SHA256 return sha256Hash(slices), crypto.SHA256
} }
if sigType == signatureECDSA {
return sha1Hash(slices), crypto.SHA1
}
return md5SHA1Hash(slices), crypto.MD5SHA1 return md5SHA1Hash(slices), crypto.MD5SHA1
} }
// ecdheRSAKeyAgreement implements a TLS key agreement where the server // ecdheRSAKeyAgreement implements a TLS key agreement where the server
// generates a ephemeral EC public/private key pair and signs it. The // generates a ephemeral EC public/private key pair and signs it. The
// pre-master secret is then calculated using ECDH. // pre-master secret is then calculated using ECDH. The signature may
type ecdheRSAKeyAgreement struct { // either be ECDSA or RSA.
type ecdheKeyAgreement struct {
version uint16 version uint16
sigType uint8
privateKey []byte privateKey []byte
curve elliptic.Curve curve elliptic.Curve
x, y *big.Int x, y *big.Int
} }
func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid uint16 var curveid uint16
Curve: Curve:
...@@ -170,10 +181,30 @@ Curve: ...@@ -170,10 +181,30 @@ Curve:
serverECDHParams[3] = byte(len(ecdhePublic)) serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic) copy(serverECDHParams[4:], ecdhePublic)
digest, hashFunc := hashForServerKeyExchange(ka.version, clientHello.random, hello.random, serverECDHParams) digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, hello.random, serverECDHParams)
sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), hashFunc, digest) var sig []byte
if err != nil { switch ka.sigType {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) case signatureECDSA:
privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
if !ok {
return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
}
r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
}
sig, err = asn1.Marshal(ecdsaSignature{r, s})
case signatureRSA:
privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("ECDHE RSA requires a RSA server private key")
}
sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
if err != nil {
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
}
default:
return nil, errors.New("unknown ECDHE signature algorithm")
} }
skx := new(serverKeyExchangeMsg) skx := new(serverKeyExchangeMsg)
...@@ -186,7 +217,7 @@ Curve: ...@@ -186,7 +217,7 @@ Curve:
k := skx.key[len(serverECDHParams):] k := skx.key[len(serverECDHParams):]
if ka.version >= VersionTLS12 { if ka.version >= VersionTLS12 {
k[0] = hashSHA256 k[0] = hashSHA256
k[1] = signatureRSA k[1] = ka.sigType
k = k[2:] k = k[2:]
} }
k[0] = byte(len(sig) >> 8) k[0] = byte(len(sig) >> 8)
...@@ -196,7 +227,7 @@ Curve: ...@@ -196,7 +227,7 @@ Curve:
return skx, nil return skx, nil
} }
func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errors.New("bad ClientKeyExchange") return nil, errors.New("bad ClientKeyExchange")
} }
...@@ -214,7 +245,7 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *C ...@@ -214,7 +245,7 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *C
var errServerKeyExchange = errors.New("invalid ServerKeyExchange") var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 4 { if len(skx.key) < 4 {
return errServerKeyExchange return errServerKeyExchange
} }
...@@ -261,11 +292,39 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH ...@@ -261,11 +292,39 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
} }
sig = sig[2:] sig = sig[2:]
digest, hashFunc := hashForServerKeyExchange(ka.version, clientHello.random, serverHello.random, serverECDHParams) digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, serverHello.random, serverECDHParams)
return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), hashFunc, digest, sig) switch ka.sigType {
case signatureECDSA:
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("ECDHE ECDSA requires a ECDSA server public key")
}
ecdsaSig := new(ecdsaSignature)
if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
return err
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
return errors.New("ECDSA signature contained zero or negative values")
}
if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
return errors.New("ECDSA verification failure")
}
case signatureRSA:
pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
return errors.New("ECDHE RSA requires a RSA server public key")
}
if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
return err
}
default:
return errors.New("unknown ECDHE signature algorithm")
}
return nil
} }
func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
if ka.curve == nil { if ka.curve == nil {
return nil, nil, errors.New("missing ServerKeyExchange message") return nil, nil, errors.New("missing ServerKeyExchange message")
} }
......
...@@ -274,11 +274,15 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte { ...@@ -274,11 +274,15 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
// hashForClientCertificate returns a digest and hash function identifier // hashForClientCertificate returns a digest and hash function identifier
// suitable for signing by a TLS client certificate. // suitable for signing by a TLS client certificate.
func (h finishedHash) hashForClientCertificate() ([]byte, crypto.Hash) { func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash) {
if h.version >= VersionTLS12 { if h.version >= VersionTLS12 {
digest := h.server.Sum(nil) digest := h.server.Sum(nil)
return digest, crypto.SHA256 return digest, crypto.SHA256
} }
if sigType == signatureECDSA {
digest := h.server.Sum(nil)
return digest, crypto.SHA1
}
digest := make([]byte, 0, 36) digest := make([]byte, 0, 36)
digest = h.serverMD5.Sum(digest) digest = h.serverMD5.Sum(digest)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment