Reviewers: golang-dev_googlegroups.com,
Message:
Hello golang-dev@googlegroups.com,
I'd like you to review this change to
https://code.google.com/p/go
Description:
crypto/tls: allow alternate low-level cryptographic functions
crypto/tls relies on the crypto/ implementations of AES, 3DES,
MD5, SHA1 and RC4. For performance or security reasons it may
be preferable to use alternate implementations (such as a Go
wrapper to OpenSSL).
This change enables use of alternate AES, 3DES, MD5, SHA1 and
RC4 function by setting global functions that crypto/tls uses
to create cipher or hash objects. By default the standard Go
implementations are used.
Please review this at https://codereview.appspot.com/7197048/
Affected files:
M src/pkg/crypto/tls/cipher_suites.go
M src/pkg/crypto/tls/key_agreement.go
M src/pkg/crypto/tls/prf.go
Index: src/pkg/crypto/tls/cipher_suites.go
===================================================================
--- a/src/pkg/crypto/tls/cipher_suites.go
+++ b/src/pkg/crypto/tls/cipher_suites.go
@@ -9,6 +9,7 @@
"crypto/cipher"
"crypto/des"
"crypto/hmac"
+ "crypto/md5"
"crypto/rc4"
"crypto/sha1"
"crypto/x509"
@@ -34,6 +35,44 @@
generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate)
([]byte, *clientKeyExchangeMsg, error)
}
+func sha1New() hash.Hash {
+ return sha1.New()
+}
+
+func md5New() hash.Hash {
+ return md5.New()
+}
+
+func rc4NewCipher(key []byte) (interface{}, error) {
+ return rc4.NewCipher(key)
+}
+
+func aesNewCipher(key []byte) (cipher.Block, error) {
+ return aes.NewCipher(key)
+}
+
+func desNewTripleDESCipher(key []byte) (cipher.Block, error) {
+ return des.NewTripleDESCipher(key)
+}
+
+// Functions that create ciphers and cryptographic hashes. Change them
+// to substitute alternative implementations
+var (
+ AESNewCipher func(key []byte) (cipher.Block, error)
+ RC4NewCipher func(key []byte) (interface{}, error)
+ DESNewTripleDESCipher func(key []byte) (cipher.Block, error)
+ MD5New func() hash.Hash
+ SHA1New func() hash.Hash
+)
+
+func init() {
+ AESNewCipher = aesNewCipher
+ RC4NewCipher = rc4NewCipher
+ DESNewTripleDESCipher = desNewTripleDESCipher
+ MD5New = md5New
+ SHA1New = sha1New
+}
+
// A cipherSuite is a specific combination of key agreement, cipher and MAC
// function. All cipher suites currently assume RSA key agreement.
type cipherSuite struct {
@@ -63,12 +102,12 @@
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
- cipher, _ := rc4.NewCipher(key)
+ cipher, _ := RC4NewCipher(key)
return cipher
}
func cipher3DES(key, iv []byte, isRead bool) interface{} {
- block, _ := des.NewTripleDESCipher(key)
+ block, _ := DESNewTripleDESCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
}
@@ -76,7 +115,7 @@
}
func cipherAES(key, iv []byte, isRead bool) interface{} {
- block, _ := aes.NewCipher(key)
+ block, _ := AESNewCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
}
@@ -87,13 +126,13 @@
func macSHA1(version uint16, key []byte) macFunction {
if version == versionSSL30 {
mac := ssl30MAC{
- h: sha1.New(),
+ h: SHA1New(),
key: make([]byte, len(key)),
}
copy(mac.key, key)
return mac
}
- return tls10MAC{hmac.New(sha1.New, key)}
+ return tls10MAC{hmac.New(SHA1New, key)}
}
type macFunction interface {
Index: src/pkg/crypto/tls/key_agreement.go
===================================================================
--- a/src/pkg/crypto/tls/key_agreement.go
+++ b/src/pkg/crypto/tls/key_agreement.go
@@ -86,13 +86,13 @@
// concatenation of an MD5 and SHA1 hash.
func md5SHA1Hash(slices ...[]byte) []byte {
md5sha1 := make([]byte, md5.Size+sha1.Size)
- hmd5 := md5.New()
+ hmd5 := MD5New()
for _, slice := range slices {
hmd5.Write(slice)
}
copy(md5sha1, hmd5.Sum(nil))
- hsha1 := sha1.New()
+ hsha1 := SHA1New()
for _, slice := range slices {
hsha1.Write(slice)
}
Index: src/pkg/crypto/tls/prf.go
===================================================================
--- a/src/pkg/crypto/tls/prf.go
+++ b/src/pkg/crypto/tls/prf.go
@@ -6,8 +6,6 @@
import (
"crypto/hmac"
- "crypto/md5"
- "crypto/sha1"
"hash"
)
@@ -45,8 +43,8 @@
// 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
+ hashSHA1 := SHA1New
+ hashMD5 := MD5New
labelAndSeed := make([]byte, len(label)+len(seed))
copy(labelAndSeed, label)
@@ -65,8 +63,8 @@
// pRF30 implements the SSL 3.0 pseudo-random function, as defined in
// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
func pRF30(result, secret, label, seed []byte) {
- hashSHA1 := sha1.New()
- hashMD5 := md5.New()
+ hashSHA1 := SHA1New()
+ hashMD5 := MD5New()
done := 0
i := 0
@@ -153,7 +151,7 @@
}
func newFinishedHash(version uint16) finishedHash {
- return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New(), version}
+ return finishedHash{MD5New(), SHA1New(), MD5New(), SHA1New(), version}
}
// A finishedHash calculates the hash of a set of handshake messages
suitable