Russ Cox | 470549d | 2012-01-25 15:31:12 -0500 | [diff] [blame] | 1 | // Copyright 2011 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package ssh |
| 6 | |
| 7 | import ( |
| 8 | "bytes" |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 9 | "crypto" |
Nathan(yinian) Hu | 5c68cfd | 2015-04-08 12:39:14 +1000 | [diff] [blame] | 10 | "crypto/aes" |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 11 | "crypto/rand" |
Russ Cox | 470549d | 2012-01-25 15:31:12 -0500 | [diff] [blame] | 12 | "testing" |
| 13 | ) |
| 14 | |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 15 | func TestDefaultCiphersExist(t *testing.T) { |
| 16 | for _, cipherAlgo := range supportedCiphers { |
| 17 | if _, ok := cipherModes[cipherAlgo]; !ok { |
| 18 | t.Errorf("default cipher %q is unknown", cipherAlgo) |
Russ Cox | 470549d | 2012-01-25 15:31:12 -0500 | [diff] [blame] | 19 | } |
| 20 | } |
| 21 | } |
| 22 | |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 23 | func TestPacketCiphers(t *testing.T) { |
Martin Hamrle | 077efaa | 2016-07-06 09:13:05 +0200 | [diff] [blame] | 24 | // Still test aes128cbc cipher although it's commented out. |
Nathan(yinian) Hu | 5c68cfd | 2015-04-08 12:39:14 +1000 | [diff] [blame] | 25 | cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} |
| 26 | defer delete(cipherModes, aes128cbcID) |
| 27 | |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 28 | for cipher := range cipherModes { |
MiLk | 84bacda | 2017-01-20 08:44:06 +0900 | [diff] [blame] | 29 | for mac := range macModes { |
| 30 | kr := &kexResult{Hash: crypto.SHA1} |
| 31 | algs := directionAlgorithms{ |
| 32 | Cipher: cipher, |
| 33 | MAC: mac, |
| 34 | Compression: "none", |
| 35 | } |
| 36 | client, err := newPacketCipher(clientKeys, algs, kr) |
| 37 | if err != nil { |
| 38 | t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) |
| 39 | continue |
| 40 | } |
| 41 | server, err := newPacketCipher(clientKeys, algs, kr) |
| 42 | if err != nil { |
| 43 | t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) |
| 44 | continue |
| 45 | } |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 46 | |
MiLk | 84bacda | 2017-01-20 08:44:06 +0900 | [diff] [blame] | 47 | want := "bla bla" |
| 48 | input := []byte(want) |
| 49 | buf := &bytes.Buffer{} |
| 50 | if err := client.writePacket(0, buf, rand.Reader, input); err != nil { |
| 51 | t.Errorf("writePacket(%q, %q): %v", cipher, mac, err) |
| 52 | continue |
| 53 | } |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 54 | |
MiLk | 84bacda | 2017-01-20 08:44:06 +0900 | [diff] [blame] | 55 | packet, err := server.readPacket(0, buf) |
| 56 | if err != nil { |
| 57 | t.Errorf("readPacket(%q, %q): %v", cipher, mac, err) |
| 58 | continue |
| 59 | } |
Adam Langley | fa50e74 | 2014-04-09 13:57:52 -0700 | [diff] [blame] | 60 | |
MiLk | 84bacda | 2017-01-20 08:44:06 +0900 | [diff] [blame] | 61 | if string(packet) != want { |
| 62 | t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want) |
| 63 | } |
Russ Cox | 470549d | 2012-01-25 15:31:12 -0500 | [diff] [blame] | 64 | } |
| 65 | } |
| 66 | } |
Han-Wen Nienhuys | 9fb97e8 | 2015-05-11 16:18:18 +0200 | [diff] [blame] | 67 | |
| 68 | func TestCBCOracleCounterMeasure(t *testing.T) { |
| 69 | cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} |
| 70 | defer delete(cipherModes, aes128cbcID) |
| 71 | |
| 72 | kr := &kexResult{Hash: crypto.SHA1} |
| 73 | algs := directionAlgorithms{ |
| 74 | Cipher: aes128cbcID, |
| 75 | MAC: "hmac-sha1", |
| 76 | Compression: "none", |
| 77 | } |
| 78 | client, err := newPacketCipher(clientKeys, algs, kr) |
| 79 | if err != nil { |
| 80 | t.Fatalf("newPacketCipher(client): %v", err) |
| 81 | } |
| 82 | |
| 83 | want := "bla bla" |
| 84 | input := []byte(want) |
| 85 | buf := &bytes.Buffer{} |
| 86 | if err := client.writePacket(0, buf, rand.Reader, input); err != nil { |
| 87 | t.Errorf("writePacket: %v", err) |
| 88 | } |
| 89 | |
| 90 | packetSize := buf.Len() |
| 91 | buf.Write(make([]byte, 2*maxPacket)) |
| 92 | |
| 93 | // We corrupt each byte, but this usually will only test the |
| 94 | // 'packet too large' or 'MAC failure' cases. |
| 95 | lastRead := -1 |
| 96 | for i := 0; i < packetSize; i++ { |
| 97 | server, err := newPacketCipher(clientKeys, algs, kr) |
| 98 | if err != nil { |
| 99 | t.Fatalf("newPacketCipher(client): %v", err) |
| 100 | } |
| 101 | |
| 102 | fresh := &bytes.Buffer{} |
| 103 | fresh.Write(buf.Bytes()) |
| 104 | fresh.Bytes()[i] ^= 0x01 |
| 105 | |
| 106 | before := fresh.Len() |
| 107 | _, err = server.readPacket(0, fresh) |
| 108 | if err == nil { |
| 109 | t.Errorf("corrupt byte %d: readPacket succeeded ", i) |
| 110 | continue |
| 111 | } |
| 112 | if _, ok := err.(cbcError); !ok { |
| 113 | t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) |
| 114 | continue |
| 115 | } |
| 116 | |
| 117 | after := fresh.Len() |
| 118 | bytesRead := before - after |
| 119 | if bytesRead < maxPacket { |
| 120 | t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) |
| 121 | continue |
| 122 | } |
| 123 | |
| 124 | if i > 0 && bytesRead != lastRead { |
Han-Wen Nienhuys | 1e856cb | 2015-06-08 19:09:00 +0200 | [diff] [blame] | 125 | t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) |
Han-Wen Nienhuys | 9fb97e8 | 2015-05-11 16:18:18 +0200 | [diff] [blame] | 126 | } |
| 127 | lastRead = bytesRead |
| 128 | } |
| 129 | } |