blob: bc2e9838061448d025e1d7036d6c43ac8d9f9a49 [file] [log] [blame]
Russ Cox470549d2012-01-25 15:31:12 -05001// 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
5package ssh
6
7import (
8 "crypto/aes"
9 "crypto/cipher"
10 "crypto/rc4"
11)
12
13// streamDump is used to dump the initial keystream for stream ciphers. It is a
14// a write-only buffer, and not intended for reading so do not require a mutex.
15var streamDump [512]byte
16
17// noneCipher implements cipher.Stream and provides no encryption. It is used
18// by the transport before the first key-exchange.
19type noneCipher struct{}
20
21func (c noneCipher) XORKeyStream(dst, src []byte) {
22 copy(dst, src)
23}
24
25func newAESCTR(key, iv []byte) (cipher.Stream, error) {
26 c, err := aes.NewCipher(key)
27 if err != nil {
28 return nil, err
29 }
30 return cipher.NewCTR(c, iv), nil
31}
32
33func newRC4(key, iv []byte) (cipher.Stream, error) {
34 return rc4.NewCipher(key)
35}
36
37type cipherMode struct {
Adam Langley63f855d2012-04-20 15:17:42 -040038 keySize int
39 ivSize int
40 skip int
41 createFunc func(key, iv []byte) (cipher.Stream, error)
Russ Cox470549d2012-01-25 15:31:12 -050042}
43
44func (c *cipherMode) createCipher(key, iv []byte) (cipher.Stream, error) {
45 if len(key) < c.keySize {
46 panic("ssh: key length too small for cipher")
47 }
48 if len(iv) < c.ivSize {
49 panic("ssh: iv too small for cipher")
50 }
51
Adam Langley63f855d2012-04-20 15:17:42 -040052 stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
Russ Cox470549d2012-01-25 15:31:12 -050053 if err != nil {
54 return nil, err
55 }
56
57 for remainingToDump := c.skip; remainingToDump > 0; {
58 dumpThisTime := remainingToDump
59 if dumpThisTime > len(streamDump) {
60 dumpThisTime = len(streamDump)
61 }
62 stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
63 remainingToDump -= dumpThisTime
64 }
65
66 return stream, nil
67}
68
69// Specifies a default set of ciphers and a preference order. This is based on
70// OpenSSH's default client preference order, minus algorithms that are not
71// implemented.
72var DefaultCipherOrder = []string{
73 "aes128-ctr", "aes192-ctr", "aes256-ctr",
74 "arcfour256", "arcfour128",
75}
76
Dave Cheney1582bf02012-10-30 18:13:59 +110077// cipherModes documents properties of supported ciphers. Ciphers not included
78// are not supported and will not be negotiated, even if explicitly requested in
79// ClientConfig.Crypto.Ciphers.
Russ Cox470549d2012-01-25 15:31:12 -050080var cipherModes = map[string]*cipherMode{
81 // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
82 // are defined in the order specified in the RFC.
83 "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
84 "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
85 "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
86
87 // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
88 // They are defined in the order specified in the RFC.
89 "arcfour128": {16, 0, 1536, newRC4},
90 "arcfour256": {32, 0, 1536, newRC4},
91}
Han-Wen Nienhuysd7d50b02013-08-28 10:50:25 -040092
93// defaultKeyExchangeOrder specifies a default set of key exchange algorithms
94// with preferences.
95var defaultKeyExchangeOrder = []string{
96 // P384 and P521 are not constant-time yet, but since we don't
97 // reuse ephemeral keys, using them for ECDH should be OK.
98 kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
99 kexAlgoDH14SHA1, kexAlgoDH1SHA1,
100}