x/crypto/ssh: add 3des-cbc as a non-default cipher
3des-cbc is an insecure cipher. As such, you must explictly add it to
Config in order to use it.
Change-Id: Ifd15cde46a9908eefef1c75bae7e97b05767361d
Reviewed-on: https://go-review.googlesource.com/22770
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
diff --git a/ssh/cipher.go b/ssh/cipher.go
index 2732963..34d3917 100644
--- a/ssh/cipher.go
+++ b/ssh/cipher.go
@@ -7,6 +7,7 @@
import (
"crypto/aes"
"crypto/cipher"
+ "crypto/des"
"crypto/rc4"
"crypto/subtle"
"encoding/binary"
@@ -121,6 +122,9 @@
// You should expect that an active attacker can recover plaintext if
// you do.
aes128cbcID: {16, aes.BlockSize, 0, nil},
+
+ // 3des-cbc is insecure and is disabled by default.
+ tripledescbcID: {24, des.BlockSize, 0, nil},
}
// prefixLen is the length of the packet prefix that contains the packet length
@@ -368,12 +372,7 @@
oracleCamouflage uint32
}
-func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
- c, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
-
+func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
cbc := &cbcCipher{
mac: macModes[algs.MAC].new(macKey),
decrypter: cipher.NewCBCDecrypter(c, iv),
@@ -387,6 +386,34 @@
return cbc, nil
}
+func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
+func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := des.NewTripleDESCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
func maxUInt32(a, b int) uint32 {
if a > b {
return uint32(a)
diff --git a/ssh/test/session_test.go b/ssh/test/session_test.go
index d27ade7..faf2d2b 100644
--- a/ssh/test/session_test.go
+++ b/ssh/test/session_test.go
@@ -280,9 +280,9 @@
var config ssh.Config
config.SetDefaults()
cipherOrder := config.Ciphers
- // This cipher will not be tested when commented out in cipher.go it will
+ // These ciphers will not be tested when commented out in cipher.go it will
// fallback to the next available as per line 292.
- cipherOrder = append(cipherOrder, "aes128-cbc")
+ cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc")
for _, ciph := range cipherOrder {
server := newServer(t)
diff --git a/ssh/transport.go b/ssh/transport.go
index bf7dd61..62fba62 100644
--- a/ssh/transport.go
+++ b/ssh/transport.go
@@ -11,8 +11,9 @@
)
const (
- gcmCipherID = "aes128-gcm@openssh.com"
- aes128cbcID = "aes128-cbc"
+ gcmCipherID = "aes128-gcm@openssh.com"
+ aes128cbcID = "aes128-cbc"
+ tripledescbcID = "3des-cbc"
)
// packetConn represents a transport that implements packet based
@@ -219,6 +220,10 @@
return newAESCBCCipher(iv, key, macKey, algs)
}
+ if algs.Cipher == tripledescbcID {
+ return newTripleDESCBCCipher(iv, key, macKey, algs)
+ }
+
c := &streamPacketCipher{
mac: macModes[algs.MAC].new(macKey),
}