]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: support CBC ciphers
authorAdam Langley <agl@golang.org>
Wed, 15 Dec 2010 16:49:55 +0000 (11:49 -0500)
committerAdam Langley <agl@golang.org>
Wed, 15 Dec 2010 16:49:55 +0000 (11:49 -0500)
This is largely based on ality's CL 2747042.

crypto/rc4: API break in order to conform to crypto/cipher's
Stream interface

cipher/cipher: promote to the default build

Since CBC differs between TLS 1.0 and 1.1, we downgrade and
support only 1.0 at the current time. 1.0 is what most of the
world uses.

Given this CL, it would be trival to add support for AES 256,
SHA 256 etc, but I haven't in order to keep the change smaller.

R=rsc
CC=ality, golang-dev
https://golang.org/cl/3659041

13 files changed:
src/pkg/Makefile
src/pkg/crypto/rc4/rc4.go
src/pkg/crypto/rc4/rc4_test.go
src/pkg/crypto/tls/Makefile
src/pkg/crypto/tls/cipher_suites.go [new file with mode: 0644]
src/pkg/crypto/tls/common.go
src/pkg/crypto/tls/conn.go
src/pkg/crypto/tls/conn_test.go [new file with mode: 0644]
src/pkg/crypto/tls/handshake_client.go
src/pkg/crypto/tls/handshake_server.go
src/pkg/crypto/tls/handshake_server_test.go
src/pkg/crypto/tls/prf.go
src/pkg/crypto/tls/prf_test.go

index aa94cb2dda63ee747b498b3f4273445e2bfed631..9f449d125841f3d4e777f0091fa22d32ba77af6d 100644 (file)
@@ -32,6 +32,7 @@ DIRS=\
        crypto/block\
        crypto/blowfish\
        crypto/cast5\
+       crypto/cipher\
        crypto/elliptic\
        crypto/hmac\
        crypto/md4\
index e47a015138602dfc235937490da9be69bca17a50..65fd195f3de47c826eb7aa39dd5eef7783b2cb4f 100644 (file)
@@ -45,14 +45,14 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
        return &c, nil
 }
 
-// XORKeyStream will XOR each byte of the given buffer with a byte of the
-// generated keystream.
-func (c *Cipher) XORKeyStream(buf []byte) {
-       for i := range buf {
+// XORKeyStream sets dst to the result of XORing src with the key stream.
+// Dst and src may be the same slice but otherwise should not overlap.
+func (c *Cipher) XORKeyStream(dst, src []byte) {
+       for i := range src {
                c.i += 1
                c.j += c.s[c.i]
                c.s[c.i], c.s[c.j] = c.s[c.j], c.s[c.i]
-               buf[i] ^= c.s[c.s[c.i]+c.s[c.j]]
+               dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]]
        }
 }
 
index 73a52e721b23f6ccfc56cc1a6c21031ea461c412..6265d9408f40bd1daf5a63b3539f1652f301901b 100644 (file)
@@ -48,7 +48,7 @@ func TestGolden(t *testing.T) {
                        return
                }
                keystream := make([]byte, len(g.keystream))
-               c.XORKeyStream(keystream)
+               c.XORKeyStream(keystream, keystream)
                for j, v := range keystream {
                        if g.keystream[j] != v {
                                t.Errorf("Failed at golden index %d", i)
index 86f9695c071be4c63d92a96de7bceaa0675c5791..1995a8a827dda97210365dc703ae5c38d86411ed 100644 (file)
@@ -8,6 +8,7 @@ TARG=crypto/tls
 GOFILES=\
        alert.go\
        ca_set.go\
+       cipher_suites.go\
        common.go\
        conn.go\
        handshake_client.go\
diff --git a/src/pkg/crypto/tls/cipher_suites.go b/src/pkg/crypto/tls/cipher_suites.go
new file mode 100644 (file)
index 0000000..c376c58
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+       "crypto/aes"
+       "crypto/cipher"
+       "crypto/hmac"
+       "crypto/rc4"
+       "hash"
+)
+
+// A cipherSuite is a specific combination of key agreement, cipher and MAC
+// function. All cipher suites currently assume RSA key agreement.
+type cipherSuite struct {
+       // the lengths, in bytes, of the key material needed for each component.
+       keyLen, macLen, ivLen int
+       cipher                func(key, iv []byte, isRead bool) interface{}
+       mac                   func(macKey []byte) hash.Hash
+}
+
+var cipherSuites = map[uint16]*cipherSuite{
+       TLS_RSA_WITH_RC4_128_SHA:     &cipherSuite{16, 20, 0, cipherRC4, hmacSHA1},
+       TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, cipherAES, hmacSHA1},
+}
+
+func cipherRC4(key, iv []byte, isRead bool) interface{} {
+       cipher, _ := rc4.NewCipher(key)
+       return cipher
+}
+
+func cipherAES(key, iv []byte, isRead bool) interface{} {
+       block, _ := aes.NewCipher(key)
+       if isRead {
+               return cipher.NewCBCDecrypter(block, iv)
+       }
+       return cipher.NewCBCEncrypter(block, iv)
+}
+
+func hmacSHA1(key []byte) hash.Hash {
+       return hmac.NewSHA1(key)
+}
+
+// mutualCipherSuite returns a cipherSuite and its id given a list of supported
+// ciphersuites and the id requested by the peer.
+func mutualCipherSuite(have []uint16, want uint16) (suite *cipherSuite, id uint16) {
+       for _, id := range have {
+               if want == id {
+                       return cipherSuites[id], id
+               }
+       }
+       return
+}
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
+const (
+       TLS_RSA_WITH_RC4_128_SHA     uint16 = 0x0005
+       TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+)
index 4fb17ad3a89182624a63cbab8c3d0abc7a6e9ac8..1cb2d850ccdd1872e2de604cd89a80531a41bfda 100644 (file)
@@ -20,7 +20,7 @@ const (
        maxHandshake    = 65536        // maximum handshake we support (protocol max is 16 MB)
 
        minVersion = 0x0301 // minimum supported version - TLS 1.0
-       maxVersion = 0x0302 // maximum supported version - TLS 1.1
+       maxVersion = 0x0301 // maximum supported version - TLS 1.0
 )
 
 // TLS record types.
@@ -47,11 +47,6 @@ const (
        typeNextProtocol       uint8 = 67 // Not IANA assigned
 )
 
-// TLS cipher suites.
-const (
-       TLS_RSA_WITH_RC4_128_SHA uint16 = 5
-)
-
 // TLS compression types.
 const (
        compressionNone uint8 = 0
@@ -120,6 +115,10 @@ type Config struct {
        // certificate nor does it require that the certificate sent be
        // anything more than self-signed.
        AuthenticateClient bool
+
+       // CipherSuites is a list of supported cipher suites. If CipherSuites
+       // is nil, TLS uses a list of suites supported by the implementation.
+       CipherSuites []uint16
 }
 
 func (c *Config) rand() io.Reader {
@@ -146,6 +145,14 @@ func (c *Config) rootCAs() *CASet {
        return s
 }
 
+func (c *Config) cipherSuites() []uint16 {
+       s := c.CipherSuites
+       if len(s) == 0 {
+               s = defaultCipherSuites()
+       }
+       return s
+}
+
 // A Certificate is a chain of one or more certificates, leaf first.
 type Certificate struct {
        Certificate [][]byte
@@ -164,11 +171,6 @@ type handshakeMessage interface {
        unmarshal([]byte) bool
 }
 
-type encryptor interface {
-       // XORKeyStream xors the contents of the slice with bytes from the key stream.
-       XORKeyStream(buf []byte)
-}
-
 // mutualVersion returns the protocol version to use given the advertised
 // version of the peer.
 func mutualVersion(vers uint16) (uint16, bool) {
@@ -199,10 +201,20 @@ var certFiles = []string{
 var once sync.Once
 
 func defaultRoots() *CASet {
-       once.Do(initDefaultRoots)
+       once.Do(initDefaults)
        return varDefaultRoots
 }
 
+func defaultCipherSuites() []uint16 {
+       once.Do(initDefaults)
+       return varDefaultCipherSuites
+}
+
+func initDefaults() {
+       initDefaultRoots()
+       initDefaultCipherSuites()
+}
+
 var varDefaultRoots *CASet
 
 func initDefaultRoots() {
@@ -216,3 +228,14 @@ func initDefaultRoots() {
        }
        varDefaultRoots = roots
 }
+
+var varDefaultCipherSuites []uint16
+
+func initDefaultCipherSuites() {
+       varDefaultCipherSuites = make([]uint16, len(cipherSuites))
+       i := 0
+       for id, _ := range cipherSuites {
+               varDefaultCipherSuites[i] = id
+               i++
+       }
+}
index 125d0a90866ee2c56f06cc59dc5ef6527f2b0106..8b1cd86af9c7472ebf89a2c94aab3a125862ed81 100644 (file)
@@ -1,9 +1,14 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 // TLS low level connection and record layer
 
 package tls
 
 import (
        "bytes"
+       "crypto/cipher"
        "crypto/subtle"
        "crypto/x509"
        "hash"
@@ -99,31 +104,31 @@ func (c *Conn) SetWriteTimeout(nsec int64) os.Error {
 // connection, either sending or receiving.
 type halfConn struct {
        sync.Mutex
-       crypt encryptor // encryption state
-       mac   hash.Hash // MAC algorithm
-       seq   [8]byte   // 64-bit sequence number
-       bfree *block    // list of free blocks
+       cipher interface{} // cipher algorithm
+       mac    hash.Hash   // MAC algorithm
+       seq    [8]byte     // 64-bit sequence number
+       bfree  *block      // list of free blocks
 
-       nextCrypt encryptor // next encryption state
-       nextMac   hash.Hash // next MAC algorithm
+       nextCipher interface{} // next encryption state
+       nextMac    hash.Hash   // next MAC algorithm
 }
 
 // prepareCipherSpec sets the encryption and MAC states
 // that a subsequent changeCipherSpec will use.
-func (hc *halfConn) prepareCipherSpec(crypt encryptor, mac hash.Hash) {
-       hc.nextCrypt = crypt
+func (hc *halfConn) prepareCipherSpec(cipher interface{}, mac hash.Hash) {
+       hc.nextCipher = cipher
        hc.nextMac = mac
 }
 
 // changeCipherSpec changes the encryption and MAC states
 // to the ones previously passed to prepareCipherSpec.
 func (hc *halfConn) changeCipherSpec() os.Error {
-       if hc.nextCrypt == nil {
+       if hc.nextCipher == nil {
                return alertInternalError
        }
-       hc.crypt = hc.nextCrypt
+       hc.cipher = hc.nextCipher
        hc.mac = hc.nextMac
-       hc.nextCrypt = nil
+       hc.nextCipher = nil
        hc.nextMac = nil
        return nil
 }
@@ -150,27 +155,102 @@ func (hc *halfConn) resetSeq() {
        }
 }
 
+// removePadding returns an unpadded slice, in constant time, which is a prefix
+// of the input. It also returns a byte which is equal to 255 if the padding
+// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func removePadding(payload []byte) ([]byte, byte) {
+       if len(payload) < 1 {
+               return payload, 0
+       }
+
+       paddingLen := payload[len(payload)-1]
+       t := uint(len(payload)-1) - uint(paddingLen)
+       // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
+       good := byte(int32(^t) >> 31)
+
+       toCheck := 255 // the maximum possible padding length
+       // The length of the padded data is public, so we can use an if here
+       if toCheck+1 > len(payload) {
+               toCheck = len(payload) - 1
+       }
+
+       for i := 0; i < toCheck; i++ {
+               t := uint(paddingLen) - uint(i)
+               // if i <= paddingLen then the MSB of t is zero
+               mask := byte(int32(^t) >> 31)
+               b := payload[len(payload)-1-i]
+               good &^= mask&paddingLen ^ mask&b
+       }
+
+       // We AND together the bits of good and replicate the result across
+       // all the bits.
+       good &= good << 4
+       good &= good << 2
+       good &= good << 1
+       good = uint8(int8(good) >> 7)
+
+       toRemove := good&paddingLen + 1
+       return payload[:len(payload)-int(toRemove)], good
+}
+
+func roundUp(a, b int) int {
+       return a + (b-a%b)%b
+}
+
 // decrypt checks and strips the mac and decrypts the data in b.
 func (hc *halfConn) decrypt(b *block) (bool, alert) {
        // pull out payload
        payload := b.data[recordHeaderLen:]
 
+       macSize := 0
+       if hc.mac != nil {
+               macSize = hc.mac.Size()
+       }
+
+       paddingGood := byte(255)
+
        // decrypt
-       if hc.crypt != nil {
-               hc.crypt.XORKeyStream(payload)
+       if hc.cipher != nil {
+               switch c := hc.cipher.(type) {
+               case cipher.Stream:
+                       c.XORKeyStream(payload, payload)
+               case cipher.BlockMode:
+                       blockSize := c.BlockSize()
+
+                       if len(payload)%blockSize != 0 || len(payload) < roundUp(macSize+1, blockSize) {
+                               return false, alertBadRecordMAC
+                       }
+
+                       c.CryptBlocks(payload, payload)
+                       payload, paddingGood = removePadding(payload)
+                       b.resize(recordHeaderLen + len(payload))
+
+                       // note that we still have a timing side-channel in the
+                       // MAC check, below. An attacker can align the record
+                       // so that a correct padding will cause one less hash
+                       // block to be calculated. Then they can iteratively
+                       // decrypt a record by breaking each byte. See
+                       // "Password Interception in a SSL/TLS Channel", Brice
+                       // Canvel et al.
+                       //
+                       // However, our behaviour matches OpenSSL, so we leak
+                       // only as much as they do.
+               default:
+                       panic("unknown cipher type")
+               }
        }
 
        // check, strip mac
        if hc.mac != nil {
-               if len(payload) < hc.mac.Size() {
+               if len(payload) < macSize {
                        return false, alertBadRecordMAC
                }
 
                // strip mac off payload, b.data
-               n := len(payload) - hc.mac.Size()
+               n := len(payload) - macSize
                b.data[3] = byte(n >> 8)
                b.data[4] = byte(n)
-               b.data = b.data[0 : recordHeaderLen+n]
+               b.resize(recordHeaderLen + n)
                remoteMAC := payload[n:]
 
                hc.mac.Reset()
@@ -178,7 +258,7 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
                hc.incSeq()
                hc.mac.Write(b.data)
 
-               if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 {
+               if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 || paddingGood != 255 {
                        return false, alertBadRecordMAC
                }
        }
@@ -186,6 +266,23 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
        return true, 0
 }
 
+// padToBlockSize calculates the needed padding block, if any, for a payload.
+// On exit, prefix aliases payload and extends to the end of the last full
+// block of payload. finalBlock is a fresh slice which contains the contents of
+// any suffix of payload as well as the needed padding to make finalBlock a
+// full block.
+func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
+       overrun := len(payload) % blockSize
+       paddingLen := blockSize - overrun
+       prefix = payload[:len(payload)-overrun]
+       finalBlock = make([]byte, blockSize)
+       copy(finalBlock, payload[len(payload)-overrun:])
+       for i := overrun; i < blockSize; i++ {
+               finalBlock[i] = byte(paddingLen - 1)
+       }
+       return
+}
+
 // encrypt encrypts and macs the data in b.
 func (hc *halfConn) encrypt(b *block) (bool, alert) {
        // mac
@@ -198,18 +295,30 @@ func (hc *halfConn) encrypt(b *block) (bool, alert) {
                n := len(b.data)
                b.resize(n + len(mac))
                copy(b.data[n:], mac)
-
-               // update length to include mac
-               n = len(b.data) - recordHeaderLen
-               b.data[3] = byte(n >> 8)
-               b.data[4] = byte(n)
        }
 
+       payload := b.data[recordHeaderLen:]
+
        // encrypt
-       if hc.crypt != nil {
-               hc.crypt.XORKeyStream(b.data[recordHeaderLen:])
+       if hc.cipher != nil {
+               switch c := hc.cipher.(type) {
+               case cipher.Stream:
+                       c.XORKeyStream(payload, payload)
+               case cipher.BlockMode:
+                       prefix, finalBlock := padToBlockSize(payload, c.BlockSize())
+                       b.resize(recordHeaderLen + len(prefix) + len(finalBlock))
+                       c.CryptBlocks(b.data[recordHeaderLen:], prefix)
+                       c.CryptBlocks(b.data[recordHeaderLen+len(prefix):], finalBlock)
+               default:
+                       panic("unknown cipher type")
+               }
        }
 
+       // update length to include MAC and any block padding needed.
+       n := len(b.data) - recordHeaderLen
+       b.data[3] = byte(n >> 8)
+       b.data[4] = byte(n)
+
        return true, 0
 }
 
diff --git a/src/pkg/crypto/tls/conn_test.go b/src/pkg/crypto/tls/conn_test.go
new file mode 100644 (file)
index 0000000..ee654ca
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+       "testing"
+)
+
+func TestRoundUp(t *testing.T) {
+       if roundUp(0, 16) != 0 ||
+               roundUp(1, 16) != 16 ||
+               roundUp(15, 16) != 16 ||
+               roundUp(16, 16) != 16 ||
+               roundUp(17, 16) != 32 {
+               t.Error("roundUp broken")
+       }
+}
+
+var paddingTests = []struct {
+       in          []byte
+       good        bool
+       expectedLen int
+}{
+       {[]byte{1, 2, 3, 4, 0}, true, 4},
+       {[]byte{1, 2, 3, 4, 0, 1}, false, 0},
+       {[]byte{1, 2, 3, 4, 99, 99}, false, 0},
+       {[]byte{1, 2, 3, 4, 1, 1}, true, 4},
+       {[]byte{1, 2, 3, 2, 2, 2}, true, 3},
+       {[]byte{1, 2, 3, 3, 3, 3}, true, 2},
+       {[]byte{1, 2, 3, 4, 3, 3}, false, 0},
+       {[]byte{1, 4, 4, 4, 4, 4}, true, 1},
+       {[]byte{5, 5, 5, 5, 5, 5}, true, 0},
+       {[]byte{6, 6, 6, 6, 6, 6}, false, 0},
+}
+
+func TestRemovePadding(t *testing.T) {
+       for i, test := range paddingTests {
+               payload, good := removePadding(test.in)
+               expectedGood := byte(255)
+               if !test.good {
+                       expectedGood = 0
+               }
+               if good != expectedGood {
+                       t.Errorf("#%d: wrong validity, want:%d got:%d", expectedGood, good)
+               }
+               if good == 255 && len(payload) != test.expectedLen {
+                       t.Errorf("#%d: got %d, want %d", i, len(payload), test.expectedLen)
+               }
+       }
+}
index 4cddba3303079355679525cc9b270952dbc12880..e5e8a1f627eec6d97759be1e789c1dff1beaf1c4 100644 (file)
@@ -5,8 +5,6 @@
 package tls
 
 import (
-       "crypto/hmac"
-       "crypto/rc4"
        "crypto/rsa"
        "crypto/subtle"
        "crypto/x509"
@@ -23,7 +21,7 @@ func (c *Conn) clientHandshake() os.Error {
 
        hello := &clientHelloMsg{
                vers:               maxVersion,
-               cipherSuites:       []uint16{TLS_RSA_WITH_RC4_128_SHA},
+               cipherSuites:       c.config.cipherSuites(),
                compressionMethods: []uint8{compressionNone},
                random:             make([]byte, 32),
                ocspStapling:       true,
@@ -61,11 +59,15 @@ func (c *Conn) clientHandshake() os.Error {
        c.vers = vers
        c.haveVers = true
 
-       if serverHello.cipherSuite != TLS_RSA_WITH_RC4_128_SHA ||
-               serverHello.compressionMethod != compressionNone {
+       if serverHello.compressionMethod != compressionNone {
                return c.sendAlert(alertUnexpectedMessage)
        }
 
+       suite, suiteId := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+       if suite == nil {
+               return c.sendAlert(alertHandshakeFailure)
+       }
+
        msg, err = c.readHandshake()
        if err != nil {
                return err
@@ -245,13 +247,12 @@ func (c *Conn) clientHandshake() os.Error {
                c.writeRecord(recordTypeHandshake, certVerify.marshal())
        }
 
-       suite := cipherSuites[0]
-       masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
-               keysFromPreMasterSecret11(preMasterSecret, hello.random, serverHello.random, suite.hashLength, suite.cipherKeyLength)
-
-       cipher, _ := rc4.NewCipher(clientKey)
+       masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+               keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
 
-       c.out.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+       clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
+       clientHash := suite.mac(clientMAC)
+       c.out.prepareCipherSpec(clientCipher, clientHash)
        c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 
        finished := new(finishedMsg)
@@ -259,8 +260,9 @@ func (c *Conn) clientHandshake() os.Error {
        finishedHash.Write(finished.marshal())
        c.writeRecord(recordTypeHandshake, finished.marshal())
 
-       cipher2, _ := rc4.NewCipher(serverKey)
-       c.in.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+       serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
+       serverHash := suite.mac(serverMAC)
+       c.in.prepareCipherSpec(serverCipher, serverHash)
        c.readRecord(recordTypeChangeCipherSpec)
        if c.err != nil {
                return c.err
@@ -282,6 +284,6 @@ func (c *Conn) clientHandshake() os.Error {
        }
 
        c.handshakeComplete = true
-       c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+       c.cipherSuite = suiteId
        return nil
 }
index 6db2a6a1bf61f97dbeb1caf72b23089fb04b3b23..29c8aadb40a537fc4437083bcafdd4e95499c373 100644 (file)
@@ -4,17 +4,7 @@
 
 package tls
 
-// The handshake goroutine reads handshake messages from the record processor
-// and outputs messages to be written on another channel. It updates the record
-// processor with the state of the connection via the control channel. In the
-// case of handshake messages that need synchronous processing (because they
-// affect the handling of the next record) the record processor knows about
-// them and either waits for a control message (Finished) or includes a reply
-// channel in the message (ChangeCipherSpec).
-
 import (
-       "crypto/hmac"
-       "crypto/rc4"
        "crypto/rsa"
        "crypto/subtle"
        "crypto/x509"
@@ -22,16 +12,6 @@ import (
        "os"
 )
 
-type cipherSuite struct {
-       id                          uint16 // The number of this suite on the wire.
-       hashLength, cipherKeyLength int
-       // TODO(agl): need a method to create the cipher and hash interfaces.
-}
-
-var cipherSuites = []cipherSuite{
-       {TLS_RSA_WITH_RC4_128_SHA, 20, 16},
-}
-
 func (c *Conn) serverHandshake() os.Error {
        config := c.config
        msg, err := c.readHandshake()
@@ -54,16 +34,13 @@ func (c *Conn) serverHandshake() os.Error {
 
        hello := new(serverHelloMsg)
 
-       // We only support a single ciphersuite so we look for it in the list
-       // of client supported suites.
-       //
-       // TODO(agl): Add additional cipher suites.
        var suite *cipherSuite
-
+       var suiteId uint16
        for _, id := range clientHello.cipherSuites {
-               for _, supported := range cipherSuites {
-                       if supported.id == id {
-                               suite = &supported
+               for _, supported := range config.cipherSuites() {
+                       if id == supported {
+                               suite = cipherSuites[id]
+                               suiteId = id
                                break
                        }
                }
@@ -83,7 +60,7 @@ func (c *Conn) serverHandshake() os.Error {
        }
 
        hello.vers = vers
-       hello.cipherSuite = suite.id
+       hello.cipherSuite = suiteId
        t := uint32(config.time())
        hello.random = make([]byte, 32)
        hello.random[0] = byte(t >> 24)
@@ -225,11 +202,12 @@ func (c *Conn) serverHandshake() os.Error {
        // wrong version anyway. See the discussion at the end of section
        // 7.4.7.1 of RFC 4346.
 
-       masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
-               keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)
+       masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
+               keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
 
-       cipher, _ := rc4.NewCipher(clientKey)
-       c.in.prepareCipherSpec(cipher, hmac.NewSHA1(clientMAC))
+       clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
+       clientHash := suite.mac(clientMAC)
+       c.in.prepareCipherSpec(clientCipher, clientHash)
        c.readRecord(recordTypeChangeCipherSpec)
        if err := c.error(); err != nil {
                return err
@@ -265,8 +243,9 @@ func (c *Conn) serverHandshake() os.Error {
 
        finishedHash.Write(clientFinished.marshal())
 
-       cipher2, _ := rc4.NewCipher(serverKey)
-       c.out.prepareCipherSpec(cipher2, hmac.NewSHA1(serverMAC))
+       serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
+       serverHash := suite.mac(serverMAC)
+       c.out.prepareCipherSpec(serverCipher, serverHash)
        c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 
        finished := new(finishedMsg)
@@ -274,7 +253,7 @@ func (c *Conn) serverHandshake() os.Error {
        c.writeRecord(recordTypeHandshake, finished.marshal())
 
        c.handshakeComplete = true
-       c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+       c.cipherSuite = suiteId
 
        return nil
 }
index efdbb660514f316abe9f1a05bc7d6b8fa341c8a6..ad82e3945f2f5d1eba11f4c4a31fc01766076df6 100644 (file)
@@ -5,8 +5,8 @@
 package tls
 
 import (
-       //      "bytes"
        "big"
+       "bytes"
        "crypto/rsa"
        "encoding/hex"
        "flag"
@@ -14,7 +14,6 @@ import (
        "net"
        "os"
        "testing"
-       //      "testing/script"
 )
 
 type zeroSource struct{}
@@ -36,6 +35,7 @@ func init() {
        testConfig.Certificates = make([]Certificate, 1)
        testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
        testConfig.Certificates[0].PrivateKey = testPrivateKey
+       testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
 }
 
 func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error) {
@@ -107,9 +107,9 @@ func TestClose(t *testing.T) {
 }
 
 
-func TestHandshakeServer(t *testing.T) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
        c, s := net.Pipe()
-       srv := Server(s, testConfig)
+       srv := Server(s, config)
        go func() {
                srv.Write([]byte("hello, world\n"))
                srv.Close()
@@ -124,15 +124,23 @@ func TestHandshakeServer(t *testing.T) {
                bb := make([]byte, len(b))
                _, err := io.ReadFull(c, bb)
                if err != nil {
-                       t.Fatalf("#%d: %s", i, err)
+                       t.Fatalf("%s #%d: %s", name, i, err)
+               }
+               if !bytes.Equal(b, bb) {
+                       t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
                }
        }
+}
 
-       if !srv.haveVers || srv.vers != 0x0302 {
-               t.Errorf("server version incorrect: %v %v", srv.haveVers, srv.vers)
-       }
+func TestHandshakeServerRC4(t *testing.T) {
+       testServerScript(t, "RC4", rc4ServerScript, testConfig)
+}
 
-       // TODO: check protocol
+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)
 }
 
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
@@ -185,109 +193,319 @@ var testPrivateKey = &rsa.PrivateKey{
 // and then running 6.out -serve to start a server and then
 // gnutls-cli --insecure --debug 100 -p 10443 localhost
 // to dump a session.
-var serverScript = [][]byte{
-       // Alternate write and read.
+var rc4ServerScript = [][]byte{
        {
-               0x16, 0x03, 0x02, 0x00, 0x71, 0x01, 0x00, 0x00, 0x6d, 0x03, 0x02, 0x4b, 0xd4, 0xee, 0x6e, 0xab,
-               0x0b, 0xc3, 0x01, 0xd6, 0x8d, 0xe0, 0x72, 0x7e, 0x6c, 0x04, 0xbe, 0x9a, 0x3c, 0xa3, 0xd8, 0x95,
-               0x28, 0x00, 0xb2, 0xe8, 0x1f, 0xdd, 0xb0, 0xec, 0xca, 0x46, 0x1f, 0x00, 0x00, 0x28, 0x00, 0x33,
-               0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38, 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
-               0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x00, 0x8c,
-               0x00, 0x8d, 0x00, 0x8b, 0x00, 0x8a, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x09, 0x00, 0x03, 0x02, 0x00,
-               0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36,
-               0x38, 0x2e, 0x30, 0x2e, 0x31, 0x30,
+               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,
+               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, 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,
        },
 
        {
-               0x16, 0x03, 0x02, 0x00, 0x2a,
-               0x02, 0x00, 0x00, 0x26, 0x03, 0x02, 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, 0x02, 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, 0x02, 0x00, 0x04,
-               0x0e, 0x00, 0x00, 0x00,
+               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, 0x02, 0x00, 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x3b, 0x7a, 0x9b, 0x05, 0xfd,
-               0x1b, 0x0d, 0x81, 0xf0, 0xac, 0x59, 0x57, 0x4e, 0xb6, 0xf5, 0x81, 0xed, 0x52, 0x78, 0xc5, 0xff,
-               0x36, 0x33, 0x9c, 0x94, 0x31, 0xc3, 0x14, 0x98, 0x5d, 0xa0, 0x49, 0x23, 0x11, 0x67, 0xdf, 0x73,
-               0x1b, 0x81, 0x0b, 0xdd, 0x10, 0xda, 0xee, 0xb5, 0x68, 0x61, 0xa9, 0xb6, 0x15, 0xae, 0x1a, 0x11,
-               0x31, 0x42, 0x2e, 0xde, 0x01, 0x4b, 0x81, 0x70, 0x03, 0xc8, 0x5b, 0xca, 0x21, 0x88, 0x25, 0xef,
-               0x89, 0xf0, 0xb7, 0xff, 0x24, 0x32, 0xd3, 0x14, 0x76, 0xe2, 0x50, 0x5c, 0x2e, 0x75, 0x9d, 0x5c,
-               0xa9, 0x80, 0x3d, 0x6f, 0xd5, 0x46, 0xd3, 0xdb, 0x42, 0x6e, 0x55, 0x81, 0x88, 0x42, 0x0e, 0x45,
-               0xfe, 0x9e, 0xe4, 0x41, 0x79, 0xcf, 0x71, 0x0e, 0xed, 0x27, 0xa8, 0x20, 0x05, 0xe9, 0x7a, 0x42,
-               0x4f, 0x05, 0x10, 0x2e, 0x52, 0x5d, 0x8c, 0x3c, 0x40, 0x49, 0x4c,
-
-               0x14, 0x03, 0x02, 0x00, 0x01, 0x01,
-
-               0x16, 0x03, 0x02, 0x00, 0x24, 0x8b, 0x12, 0x24, 0x06, 0xaa, 0x92, 0x74, 0xa1, 0x46, 0x6f, 0xc1,
-               0x4e, 0x4a, 0xf7, 0x16, 0xdd, 0xd6, 0xe1, 0x2d, 0x37, 0x0b, 0x44, 0xba, 0xeb, 0xc4, 0x6c, 0xc7,
-               0xa0, 0xb7, 0x8c, 0x9d, 0x24, 0xbd, 0x99, 0x33, 0x1e,
+               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,
        },
 
        {
-               0x14, 0x03, 0x02, 0x00, 0x01,
-               0x01,
+               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,
+       },
+}
 
-               0x16, 0x03, 0x02, 0x00, 0x24,
-               0x6e, 0xd1, 0x3e, 0x49, 0x68, 0xc1, 0xa0, 0xa5, 0xb7, 0xaf, 0xb0, 0x7c, 0x52, 0x1f, 0xf7, 0x2d,
-               0x51, 0xf3, 0xa5, 0xb6, 0xf6, 0xd4, 0x18, 0x4b, 0x7a, 0xd5, 0x24, 0x1d, 0x09, 0xb6, 0x41, 0x1c,
-               0x1c, 0x98, 0xf6, 0x90,
+var aesServerScript = [][]byte{
+       {
+               0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
+               0x7b, 0x03, 0x02, 0x4d, 0x08, 0x2d, 0x0b, 0xb3,
+               0x57, 0x85, 0x71, 0x4b, 0xfb, 0x34, 0xab, 0x16,
+               0xd4, 0x92, 0x50, 0x81, 0x16, 0x95, 0x11, 0x28,
+               0x1a, 0xcb, 0xff, 0x09, 0x4d, 0x23, 0xa6, 0xfe,
+               0x2e, 0xbb, 0x78, 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, 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,
+       },
 
-               0x17, 0x03, 0x02, 0x00, 0x21,
-               0x50, 0xb7, 0x92, 0x4f, 0xd8, 0x78, 0x29, 0xa2, 0xe7, 0xa5, 0xa6, 0xbd, 0x1a, 0x0c, 0xf1, 0x5a,
-               0x6e, 0x6c, 0xeb, 0x38, 0x99, 0x9b, 0x3c, 0xfd, 0xee, 0x53, 0xe8, 0x4d, 0x7b, 0xa5, 0x5b, 0x00,
+       {
+               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, 0x2f, 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,
+       },
 
-               0xb9,
+       {
+               0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+               0x82, 0x00, 0x80, 0x71, 0x9c, 0xe7, 0x23, 0xfc,
+               0xb9, 0x19, 0x29, 0x82, 0xbf, 0xef, 0x08, 0xf7,
+               0x99, 0x36, 0xc3, 0x4c, 0x6f, 0x05, 0xd2, 0x8b,
+               0x62, 0x2b, 0x19, 0x9b, 0x7f, 0xc0, 0xcc, 0x48,
+               0x30, 0x5f, 0xcd, 0xc3, 0x70, 0x55, 0x53, 0x73,
+               0xfa, 0x79, 0x74, 0xf3, 0xa3, 0x76, 0x9f, 0xa1,
+               0x7f, 0x98, 0xc2, 0xc0, 0xe3, 0xc5, 0xa0, 0x31,
+               0x2f, 0xa6, 0xe8, 0x1e, 0x61, 0x46, 0xb3, 0x9b,
+               0x4b, 0x16, 0xf1, 0x2d, 0xc7, 0x63, 0x7f, 0x79,
+               0x22, 0x30, 0xd1, 0xf2, 0xfc, 0x77, 0x98, 0x0a,
+               0x16, 0x11, 0x63, 0x71, 0x7f, 0x70, 0xef, 0x16,
+               0xbb, 0x39, 0x87, 0x34, 0xac, 0x49, 0xbd, 0x07,
+               0x67, 0xcb, 0x9c, 0xcc, 0xde, 0xef, 0xb1, 0xe0,
+               0xdb, 0x01, 0xb5, 0x35, 0xa9, 0xb3, 0x10, 0x0c,
+               0x4b, 0xee, 0xb3, 0x4e, 0xfd, 0xbe, 0x15, 0x27,
+               0xf0, 0x46, 0xb2, 0x38, 0xba, 0x5f, 0xcc, 0x89,
+               0xec, 0x29, 0x82, 0x14, 0x03, 0x01, 0x00, 0x01,
+               0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x3c, 0xfb,
+               0xa4, 0x12, 0xcb, 0x00, 0xf9, 0x57, 0x7e, 0x9b,
+               0xc9, 0xdc, 0x0c, 0xba, 0x9a, 0x81, 0x62, 0xfb,
+               0x26, 0x13, 0x53, 0xfe, 0xaa, 0xcc, 0x82, 0xbb,
+               0xb6, 0x67, 0x7f, 0x39, 0xbe, 0x4d, 0xbb, 0xc0,
+               0x6c, 0x24, 0x31, 0x83, 0xa5, 0x50, 0x3a, 0x75,
+               0x32, 0x64, 0xb5, 0xdb, 0xbe, 0x0a,
+       },
 
-               0x15, 0x03, 0x02, 0x00, 0x16,
-               0xc7, 0xc9, 0x5a, 0x72, 0xfb, 0x02, 0xa5, 0x93, 0xdd, 0x69, 0xeb, 0x30, 0x68, 0x5e, 0xbc, 0xe0,
-               0x44, 0xb9, 0x59, 0x33, 0x68, 0xa9,
+       {
+               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+               0x01, 0x00, 0x30, 0x43, 0x24, 0x42, 0x55, 0x08,
+               0xe4, 0xc2, 0x15, 0xc9, 0xdb, 0x71, 0x69, 0xee,
+               0x09, 0xc5, 0x1c, 0xfd, 0x46, 0x10, 0xa0, 0x68,
+               0x21, 0xf2, 0x48, 0xac, 0x6c, 0xc0, 0x2b, 0x62,
+               0x07, 0x8f, 0x48, 0x33, 0x0a, 0x6b, 0x62, 0x28,
+               0x2e, 0x2c, 0xad, 0xcb, 0x34, 0x85, 0xca, 0x2e,
+               0xcd, 0x84, 0xf0,
        },
 }
index b206d26a4ab29a0f819507167ac4bb1472df0d49..478cf65f91c41f4795ae6f88febe89b7079d8cf8 100644 (file)
@@ -44,8 +44,8 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) {
        }
 }
 
-// pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5.
-func pRF11(result, secret, label, seed []byte) {
+// pRF10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func pRF10(result, secret, label, seed []byte) {
        hashSHA1 := sha1.New
        hashMD5 := md5.New
 
@@ -75,25 +75,32 @@ var clientFinishedLabel = []byte("client finished")
 var serverFinishedLabel = []byte("server finished")
 
 // keysFromPreMasterSecret generates the connection keys from the pre master
-// secret, given the lengths of the MAC and cipher keys, as defined in RFC
-// 4346, section 6.3.
-func keysFromPreMasterSecret11(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
+// secret, given the lengths of the MAC key, cipher key and IV, as defined in
+// RFC 2246, section 6.3.
+func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
        var seed [tlsRandomLength * 2]byte
        copy(seed[0:len(clientRandom)], clientRandom)
        copy(seed[len(clientRandom):], serverRandom)
        masterSecret = make([]byte, masterSecretLength)
-       pRF11(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+       pRF10(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
 
        copy(seed[0:len(clientRandom)], serverRandom)
        copy(seed[len(serverRandom):], clientRandom)
 
-       n := 2*macLen + 2*keyLen
+       n := 2*macLen + 2*keyLen + 2*ivLen
        keyMaterial := make([]byte, n)
-       pRF11(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
-       clientMAC = keyMaterial[0:macLen]
-       serverMAC = keyMaterial[macLen : macLen*2]
-       clientKey = keyMaterial[macLen*2 : macLen*2+keyLen]
-       serverKey = keyMaterial[macLen*2+keyLen:]
+       pRF10(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+       clientMAC = keyMaterial[:macLen]
+       keyMaterial = keyMaterial[macLen:]
+       serverMAC = keyMaterial[:macLen]
+       keyMaterial = keyMaterial[macLen:]
+       clientKey = keyMaterial[:keyLen]
+       keyMaterial = keyMaterial[keyLen:]
+       serverKey = keyMaterial[:keyLen]
+       keyMaterial = keyMaterial[keyLen:]
+       clientIV = keyMaterial[:ivLen]
+       keyMaterial = keyMaterial[ivLen:]
+       serverIV = keyMaterial[:ivLen]
        return
 }
 
@@ -125,7 +132,7 @@ func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
        copy(seed, md5)
        copy(seed[len(md5):], sha1)
        out := make([]byte, finishedVerifyLength)
-       pRF11(out, masterSecret, label, seed)
+       pRF10(out, masterSecret, label, seed)
        return out
 }
 
index d99bab5b5e52d159a623b4bf56e89b21ceaa3f0c..f8c4acb9d28b309ea2596bd14f87aa35f098c799 100644 (file)
@@ -47,7 +47,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
                in, _ := hex.DecodeString(test.preMasterSecret)
                clientRandom, _ := hex.DecodeString(test.clientRandom)
                serverRandom, _ := hex.DecodeString(test.serverRandom)
-               master, clientMAC, serverMAC, clientKey, serverKey := keysFromPreMasterSecret11(in, clientRandom, serverRandom, test.macLen, test.keyLen)
+               master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret10(in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
                masterString := hex.EncodeToString(master)
                clientMACString := hex.EncodeToString(clientMAC)
                serverMACString := hex.EncodeToString(serverMAC)