cipher.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. package ssh
  5. import (
  6. "crypto/aes"
  7. "crypto/cipher"
  8. "crypto/rc4"
  9. )
  10. // streamDump is used to dump the initial keystream for stream ciphers. It is a
  11. // a write-only buffer, and not intended for reading so do not require a mutex.
  12. var streamDump [512]byte
  13. // noneCipher implements cipher.Stream and provides no encryption. It is used
  14. // by the transport before the first key-exchange.
  15. type noneCipher struct{}
  16. func (c noneCipher) XORKeyStream(dst, src []byte) {
  17. copy(dst, src)
  18. }
  19. func newAESCTR(key, iv []byte) (cipher.Stream, error) {
  20. c, err := aes.NewCipher(key)
  21. if err != nil {
  22. return nil, err
  23. }
  24. return cipher.NewCTR(c, iv), nil
  25. }
  26. func newRC4(key, iv []byte) (cipher.Stream, error) {
  27. return rc4.NewCipher(key)
  28. }
  29. type cipherMode struct {
  30. keySize int
  31. ivSize int
  32. skip int
  33. createFunc func(key, iv []byte) (cipher.Stream, error)
  34. }
  35. func (c *cipherMode) createCipher(key, iv []byte) (cipher.Stream, error) {
  36. if len(key) < c.keySize {
  37. panic("ssh: key length too small for cipher")
  38. }
  39. if len(iv) < c.ivSize {
  40. panic("ssh: iv too small for cipher")
  41. }
  42. stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
  43. if err != nil {
  44. return nil, err
  45. }
  46. for remainingToDump := c.skip; remainingToDump > 0; {
  47. dumpThisTime := remainingToDump
  48. if dumpThisTime > len(streamDump) {
  49. dumpThisTime = len(streamDump)
  50. }
  51. stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
  52. remainingToDump -= dumpThisTime
  53. }
  54. return stream, nil
  55. }
  56. // Specifies a default set of ciphers and a preference order. This is based on
  57. // OpenSSH's default client preference order, minus algorithms that are not
  58. // implemented.
  59. var DefaultCipherOrder = []string{
  60. "aes128-ctr", "aes192-ctr", "aes256-ctr",
  61. "arcfour256", "arcfour128",
  62. }
  63. var cipherModes = map[string]*cipherMode{
  64. // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
  65. // are defined in the order specified in the RFC.
  66. "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
  67. "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
  68. "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
  69. // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
  70. // They are defined in the order specified in the RFC.
  71. "arcfour128": {16, 0, 1536, newRC4},
  72. "arcfour256": {32, 0, 1536, newRC4},
  73. }