crypto/tls: support CBC ciphers

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
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 6db2a6a..29c8aad 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -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 @@
 	"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 @@
 
 	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 @@
 	}
 
 	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 @@
 	// 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 @@
 
 	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 @@
 	c.writeRecord(recordTypeHandshake, finished.marshal())
 
 	c.handshakeComplete = true
-	c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
+	c.cipherSuite = suiteId
 
 	return nil
 }