aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh/common.go21
-rw-r--r--ssh/handshake_test.go23
-rw-r--r--ssh/transport.go10
3 files changed, 45 insertions, 9 deletions
diff --git a/ssh/common.go b/ssh/common.go
index 5ae2275..ec1f839 100644
--- a/ssh/common.go
+++ b/ssh/common.go
@@ -152,6 +152,11 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
return 1 << 30
}
+var aeadCiphers = map[string]bool{
+ gcmCipherID: true,
+ chacha20Poly1305ID: true,
+}
+
type algorithms struct {
kex string
hostKey string
@@ -187,14 +192,18 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
return
}
- ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
- if err != nil {
- return
+ if !aeadCiphers[ctos.Cipher] {
+ ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+ if err != nil {
+ return
+ }
}
- stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
- if err != nil {
- return
+ if !aeadCiphers[stoc.Cipher] {
+ stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+ if err != nil {
+ return
+ }
}
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
diff --git a/ssh/handshake_test.go b/ssh/handshake_test.go
index 02fbe83..46bfd6d 100644
--- a/ssh/handshake_test.go
+++ b/ssh/handshake_test.go
@@ -560,3 +560,26 @@ func TestHandshakeRekeyDefault(t *testing.T) {
t.Errorf("got rekey after %dG write, want 64G", wgb)
}
}
+
+func TestHandshakeAEADCipherNoMAC(t *testing.T) {
+ for _, cipher := range []string{chacha20Poly1305ID, gcmCipherID} {
+ checker := &syncChecker{
+ called: make(chan int, 1),
+ }
+ clientConf := &ClientConfig{
+ Config: Config{
+ Ciphers: []string{cipher},
+ MACs: []string{},
+ },
+ HostKeyCallback: checker.Check,
+ }
+ trC, trS, err := handshakePair(clientConf, "addr", false)
+ if err != nil {
+ t.Fatalf("handshakePair: %v", err)
+ }
+ defer trC.Close()
+ defer trS.Close()
+
+ <-checker.called
+ }
+}
diff --git a/ssh/transport.go b/ssh/transport.go
index 49ddc2e..acf5a21 100644
--- a/ssh/transport.go
+++ b/ssh/transport.go
@@ -238,15 +238,19 @@ var (
// (to setup server->client keys) or clientKeys (for client->server keys).
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher]
- macMode := macModes[algs.MAC]
iv := make([]byte, cipherMode.ivSize)
key := make([]byte, cipherMode.keySize)
- macKey := make([]byte, macMode.keySize)
generateKeyMaterial(iv, d.ivTag, kex)
generateKeyMaterial(key, d.keyTag, kex)
- generateKeyMaterial(macKey, d.macKeyTag, kex)
+
+ var macKey []byte
+ if !aeadCiphers[algs.Cipher] {
+ macMode := macModes[algs.MAC]
+ macKey = make([]byte, macMode.keySize)
+ generateKeyMaterial(macKey, d.macKeyTag, kex)
+ }
return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
}