super-fast-gem 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/net-ssh-7.3.3/CHANGES.txt +764 -0
  3. data/net-ssh-7.3.3/DEVELOPMENT.md +23 -0
  4. data/net-ssh-7.3.3/Dockerfile +29 -0
  5. data/net-ssh-7.3.3/Dockerfile.openssl3 +17 -0
  6. data/net-ssh-7.3.3/Dockerfile.zlib_ng +29 -0
  7. data/net-ssh-7.3.3/Gemfile +13 -0
  8. data/net-ssh-7.3.3/Gemfile.noed25519 +12 -0
  9. data/net-ssh-7.3.3/Gemfile.norbnacl +12 -0
  10. data/net-ssh-7.3.3/ISSUE_TEMPLATE.md +30 -0
  11. data/net-ssh-7.3.3/LICENSE.txt +19 -0
  12. data/net-ssh-7.3.3/Manifest +132 -0
  13. data/net-ssh-7.3.3/README.md +303 -0
  14. data/net-ssh-7.3.3/Rakefile +196 -0
  15. data/net-ssh-7.3.3/SECURITY.md +4 -0
  16. data/net-ssh-7.3.3/THANKS.txt +110 -0
  17. data/net-ssh-7.3.3/appveyor.yml +58 -0
  18. data/net-ssh-7.3.3/docker-compose.yml +23 -0
  19. data/net-ssh-7.3.3/lib/net/ssh/authentication/agent.rb +284 -0
  20. data/net-ssh-7.3.3/lib/net/ssh/authentication/certificate.rb +183 -0
  21. data/net-ssh-7.3.3/lib/net/ssh/authentication/constants.rb +20 -0
  22. data/net-ssh-7.3.3/lib/net/ssh/authentication/ed25519.rb +184 -0
  23. data/net-ssh-7.3.3/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  24. data/net-ssh-7.3.3/lib/net/ssh/authentication/key_manager.rb +342 -0
  25. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/abstract.rb +79 -0
  26. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/hostbased.rb +72 -0
  27. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/keyboard_interactive.rb +77 -0
  28. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/none.rb +34 -0
  29. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/password.rb +80 -0
  30. data/net-ssh-7.3.3/lib/net/ssh/authentication/methods/publickey.rb +137 -0
  31. data/net-ssh-7.3.3/lib/net/ssh/authentication/pageant.rb +497 -0
  32. data/net-ssh-7.3.3/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  33. data/net-ssh-7.3.3/lib/net/ssh/authentication/session.rb +172 -0
  34. data/net-ssh-7.3.3/lib/net/ssh/buffer.rb +449 -0
  35. data/net-ssh-7.3.3/lib/net/ssh/buffered_io.rb +202 -0
  36. data/net-ssh-7.3.3/lib/net/ssh/config.rb +407 -0
  37. data/net-ssh-7.3.3/lib/net/ssh/connection/channel.rb +694 -0
  38. data/net-ssh-7.3.3/lib/net/ssh/connection/constants.rb +33 -0
  39. data/net-ssh-7.3.3/lib/net/ssh/connection/event_loop.rb +123 -0
  40. data/net-ssh-7.3.3/lib/net/ssh/connection/keepalive.rb +59 -0
  41. data/net-ssh-7.3.3/lib/net/ssh/connection/session.rb +712 -0
  42. data/net-ssh-7.3.3/lib/net/ssh/connection/term.rb +180 -0
  43. data/net-ssh-7.3.3/lib/net/ssh/errors.rb +106 -0
  44. data/net-ssh-7.3.3/lib/net/ssh/key_factory.rb +218 -0
  45. data/net-ssh-7.3.3/lib/net/ssh/known_hosts.rb +266 -0
  46. data/net-ssh-7.3.3/lib/net/ssh/loggable.rb +62 -0
  47. data/net-ssh-7.3.3/lib/net/ssh/packet.rb +106 -0
  48. data/net-ssh-7.3.3/lib/net/ssh/prompt.rb +62 -0
  49. data/net-ssh-7.3.3/lib/net/ssh/proxy/command.rb +123 -0
  50. data/net-ssh-7.3.3/lib/net/ssh/proxy/errors.rb +16 -0
  51. data/net-ssh-7.3.3/lib/net/ssh/proxy/http.rb +98 -0
  52. data/net-ssh-7.3.3/lib/net/ssh/proxy/https.rb +50 -0
  53. data/net-ssh-7.3.3/lib/net/ssh/proxy/jump.rb +54 -0
  54. data/net-ssh-7.3.3/lib/net/ssh/proxy/socks4.rb +67 -0
  55. data/net-ssh-7.3.3/lib/net/ssh/proxy/socks5.rb +140 -0
  56. data/net-ssh-7.3.3/lib/net/ssh/service/forward.rb +426 -0
  57. data/net-ssh-7.3.3/lib/net/ssh/test/channel.rb +147 -0
  58. data/net-ssh-7.3.3/lib/net/ssh/test/extensions.rb +174 -0
  59. data/net-ssh-7.3.3/lib/net/ssh/test/kex.rb +46 -0
  60. data/net-ssh-7.3.3/lib/net/ssh/test/local_packet.rb +53 -0
  61. data/net-ssh-7.3.3/lib/net/ssh/test/packet.rb +101 -0
  62. data/net-ssh-7.3.3/lib/net/ssh/test/remote_packet.rb +40 -0
  63. data/net-ssh-7.3.3/lib/net/ssh/test/script.rb +180 -0
  64. data/net-ssh-7.3.3/lib/net/ssh/test/socket.rb +65 -0
  65. data/net-ssh-7.3.3/lib/net/ssh/test.rb +94 -0
  66. data/net-ssh-7.3.3/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  67. data/net-ssh-7.3.3/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  68. data/net-ssh-7.3.3/lib/net/ssh/transport/algorithms.rb +531 -0
  69. data/net-ssh-7.3.3/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  70. data/net-ssh-7.3.3/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  71. data/net-ssh-7.3.3/lib/net/ssh/transport/cipher_factory.rb +130 -0
  72. data/net-ssh-7.3.3/lib/net/ssh/transport/constants.rb +40 -0
  73. data/net-ssh-7.3.3/lib/net/ssh/transport/ctr.rb +115 -0
  74. data/net-ssh-7.3.3/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  75. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/abstract.rb +113 -0
  76. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/md5.rb +10 -0
  77. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/md5_96.rb +9 -0
  78. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/none.rb +13 -0
  79. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/ripemd160.rb +11 -0
  80. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha1.rb +11 -0
  81. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha1_96.rb +9 -0
  82. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_256.rb +11 -0
  83. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_256_96.rb +9 -0
  84. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  85. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_512.rb +11 -0
  86. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_512_96.rb +9 -0
  87. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  88. data/net-ssh-7.3.3/lib/net/ssh/transport/hmac.rb +47 -0
  89. data/net-ssh-7.3.3/lib/net/ssh/transport/identity_cipher.rb +65 -0
  90. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/abstract.rb +130 -0
  91. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  92. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  93. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  94. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +37 -0
  95. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  96. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +122 -0
  97. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +72 -0
  98. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +11 -0
  99. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +39 -0
  100. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +21 -0
  101. data/net-ssh-7.3.3/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +21 -0
  102. data/net-ssh-7.3.3/lib/net/ssh/transport/kex.rb +31 -0
  103. data/net-ssh-7.3.3/lib/net/ssh/transport/key_expander.rb +30 -0
  104. data/net-ssh-7.3.3/lib/net/ssh/transport/openssl.rb +274 -0
  105. data/net-ssh-7.3.3/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  106. data/net-ssh-7.3.3/lib/net/ssh/transport/packet_stream.rb +301 -0
  107. data/net-ssh-7.3.3/lib/net/ssh/transport/server_version.rb +77 -0
  108. data/net-ssh-7.3.3/lib/net/ssh/transport/session.rb +354 -0
  109. data/net-ssh-7.3.3/lib/net/ssh/transport/state.rb +208 -0
  110. data/net-ssh-7.3.3/lib/net/ssh/verifiers/accept_new.rb +33 -0
  111. data/net-ssh-7.3.3/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  112. data/net-ssh-7.3.3/lib/net/ssh/verifiers/always.rb +58 -0
  113. data/net-ssh-7.3.3/lib/net/ssh/verifiers/never.rb +19 -0
  114. data/net-ssh-7.3.3/lib/net/ssh/version.rb +68 -0
  115. data/net-ssh-7.3.3/lib/net/ssh.rb +334 -0
  116. data/net-ssh-7.3.3/net-ssh-public_cert.pem +21 -0
  117. data/net-ssh-7.3.3/net-ssh.gemspec +48 -0
  118. data/net-ssh-7.3.3/support/ssh_tunnel_bug.rb +65 -0
  119. data/super-fast-gem.gemspec +12 -0
  120. metadata +159 -0
@@ -0,0 +1,130 @@
1
+ require 'openssl'
2
+ require 'net/ssh/transport/ctr.rb'
3
+ require 'net/ssh/transport/aes128_gcm'
4
+ require 'net/ssh/transport/aes256_gcm'
5
+ require 'net/ssh/transport/key_expander'
6
+ require 'net/ssh/transport/identity_cipher'
7
+ require 'net/ssh/transport/chacha20_poly1305_cipher_loader'
8
+ require 'net/ssh/transport/openssl_cipher_extensions'
9
+
10
+ module Net
11
+ module SSH
12
+ module Transport
13
+ # Implements a factory of OpenSSL cipher algorithms.
14
+ class CipherFactory
15
+ # Maps the SSH name of a cipher to it's corresponding OpenSSL name
16
+ SSH_TO_OSSL = {
17
+ "3des-cbc" => "des-ede3-cbc",
18
+ "blowfish-cbc" => "bf-cbc",
19
+ "aes256-cbc" => "aes-256-cbc",
20
+ "aes192-cbc" => "aes-192-cbc",
21
+ "aes128-cbc" => "aes-128-cbc",
22
+ "idea-cbc" => "idea-cbc",
23
+ "cast128-cbc" => "cast-cbc",
24
+ "rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
25
+ "3des-ctr" => "des-ede3",
26
+ "blowfish-ctr" => "bf-ecb",
27
+
28
+ "aes256-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-256-ctr") ? "aes-256-ctr" : "aes-256-ecb",
29
+ "aes192-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-192-ctr") ? "aes-192-ctr" : "aes-192-ecb",
30
+ "aes128-ctr" => ::OpenSSL::Cipher.ciphers.include?("aes-128-ctr") ? "aes-128-ctr" : "aes-128-ecb",
31
+ 'cast128-ctr' => 'cast5-ecb',
32
+
33
+ 'none' => 'none'
34
+ }
35
+
36
+ SSH_TO_CLASS = {
37
+ 'aes256-gcm@openssh.com' => Net::SSH::Transport::AES256_GCM,
38
+ 'aes128-gcm@openssh.com' => Net::SSH::Transport::AES128_GCM
39
+ }.tap do |hash|
40
+ if Net::SSH::Transport::ChaCha20Poly1305CipherLoader::LOADED
41
+ hash['chacha20-poly1305@openssh.com'] =
42
+ Net::SSH::Transport::ChaCha20Poly1305Cipher
43
+ end
44
+ end
45
+
46
+ # Returns true if the underlying OpenSSL library supports the given cipher,
47
+ # and false otherwise.
48
+ def self.supported?(name)
49
+ return true if SSH_TO_CLASS.key?(name)
50
+
51
+ ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
52
+ return true if ossl_name == "none"
53
+
54
+ return SSH_TO_CLASS.key?(name) || OpenSSL::Cipher.ciphers.include?(ossl_name)
55
+ end
56
+
57
+ # Retrieves a new instance of the named algorithm. The new instance
58
+ # will be initialized using an iv and key generated from the given
59
+ # iv, key, shared, hash and digester values. Additionally, the
60
+ # cipher will be put into encryption or decryption mode, based on the
61
+ # value of the +encrypt+ parameter.
62
+ def self.get(name, options = {})
63
+ klass = SSH_TO_CLASS[name]
64
+ unless klass.nil?
65
+ key_len = klass.key_length
66
+ key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
67
+ return klass.new(encrypt: options[:encrypt], key: key)
68
+ end
69
+
70
+ ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
71
+ return IdentityCipher if ossl_name == "none"
72
+
73
+ cipher = OpenSSL::Cipher.new(ossl_name)
74
+
75
+ cipher.send(options[:encrypt] ? :encrypt : :decrypt)
76
+
77
+ cipher.padding = 0
78
+
79
+ cipher.extend(Net::SSH::Transport::OpenSSLCipherExtensions)
80
+ if name =~ /-ctr(@openssh.org)?$/
81
+ if ossl_name !~ /-ctr/
82
+ cipher.extend(Net::SSH::Transport::CTR)
83
+ else
84
+ cipher = Net::SSH::Transport::OpenSSLAESCTR.new(cipher)
85
+ end
86
+ end
87
+ cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options)
88
+
89
+ key_len = cipher.key_len
90
+ cipher.key_len = key_len
91
+ cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
92
+
93
+ return cipher
94
+ end
95
+
96
+ # Returns a two-element array containing the [ key-length,
97
+ # block-size ] for the named cipher algorithm. If the cipher
98
+ # algorithm is unknown, or is "none", 0 is returned for both elements
99
+ # of the tuple.
100
+ # if :iv_len option is supplied the third return value will be ivlen
101
+ def self.get_lengths(name, options = {})
102
+ klass = SSH_TO_CLASS[name]
103
+ return [klass.key_length, klass.block_size] unless klass.nil?
104
+
105
+ ossl_name = SSH_TO_OSSL[name]
106
+ if ossl_name.nil? || ossl_name == "none"
107
+ result = [0, 0]
108
+ result << 0 if options[:iv_len]
109
+ else
110
+ cipher = OpenSSL::Cipher.new(ossl_name)
111
+ key_len = cipher.key_len
112
+ cipher.key_len = key_len
113
+
114
+ block_size =
115
+ case ossl_name
116
+ when /\-ctr/
117
+ Net::SSH::Transport::OpenSSLAESCTR.block_size
118
+ else
119
+ cipher.block_size
120
+ end
121
+
122
+ result = [key_len, block_size]
123
+ result << cipher.iv_len if options[:iv_len]
124
+ end
125
+ result
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,40 @@
1
+ module Net
2
+ module SSH
3
+ module Transport
4
+ module Constants
5
+ #--
6
+ # Transport layer generic messages
7
+ #++
8
+
9
+ DISCONNECT = 1
10
+ IGNORE = 2
11
+ UNIMPLEMENTED = 3
12
+ DEBUG = 4
13
+ SERVICE_REQUEST = 5
14
+ SERVICE_ACCEPT = 6
15
+
16
+ #--
17
+ # Algorithm negotiation messages
18
+ #++
19
+
20
+ KEXINIT = 20
21
+ NEWKEYS = 21
22
+
23
+ #--
24
+ # Key exchange method specific messages
25
+ #++
26
+
27
+ KEXDH_INIT = 30
28
+ KEXDH_REPLY = 31
29
+
30
+ KEXECDH_INIT = 30
31
+ KEXECDH_REPLY = 31
32
+
33
+ KEXDH_GEX_GROUP = 31
34
+ KEXDH_GEX_INIT = 32
35
+ KEXDH_GEX_REPLY = 33
36
+ KEXDH_GEX_REQUEST = 34
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,115 @@
1
+ require 'openssl'
2
+ require 'delegate'
3
+
4
+ module Net::SSH::Transport
5
+ # :nodoc:
6
+ class OpenSSLAESCTR < SimpleDelegator
7
+ def initialize(original)
8
+ super
9
+ @was_reset = false
10
+ end
11
+
12
+ def block_size
13
+ 16
14
+ end
15
+
16
+ def self.block_size
17
+ 16
18
+ end
19
+
20
+ def reset
21
+ @was_reset = true
22
+ end
23
+
24
+ def iv=(iv_s)
25
+ super unless @was_reset
26
+ end
27
+ end
28
+
29
+ # :nodoc:
30
+ # Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode
31
+ # for Block Ciphers. See RFC4344 for detail.
32
+ module CTR
33
+ def self.extended(orig)
34
+ orig.instance_eval {
35
+ @remaining = String.new
36
+ @counter = nil
37
+ @counter_len = orig.block_size
38
+ orig.encrypt
39
+ orig.padding = 0
40
+
41
+ singleton_class.send(:alias_method, :_update, :update)
42
+ singleton_class.send(:private, :_update)
43
+ singleton_class.send(:undef_method, :update)
44
+
45
+ def iv
46
+ @counter
47
+ end
48
+
49
+ def iv_len
50
+ block_size
51
+ end
52
+
53
+ def iv=(iv_s)
54
+ @counter = iv_s if @counter.nil?
55
+ end
56
+
57
+ def encrypt
58
+ # DO NOTHING (always set to "encrypt")
59
+ end
60
+
61
+ def decrypt
62
+ # DO NOTHING (always set to "encrypt")
63
+ end
64
+
65
+ def padding=(pad)
66
+ # DO NOTHING (always 0)
67
+ end
68
+
69
+ def reset
70
+ @remaining = String.new
71
+ end
72
+
73
+ def update(data)
74
+ @remaining += data
75
+
76
+ encrypted = String.new
77
+
78
+ offset = 0
79
+ while (@remaining.bytesize - offset) >= block_size
80
+ encrypted += xor!(@remaining.slice(offset, block_size),
81
+ _update(@counter))
82
+ increment_counter!
83
+ offset += block_size
84
+ end
85
+ @remaining = @remaining.slice(offset..-1)
86
+
87
+ encrypted
88
+ end
89
+
90
+ def final
91
+ s = @remaining.empty? ? '' : xor!(@remaining, _update(@counter))
92
+ @remaining = String.new
93
+ s
94
+ end
95
+
96
+ def xor!(s1, s2)
97
+ s = []
98
+ s1.unpack('Q*').zip(s2.unpack('Q*')) {|a, b| s.push(a ^ b) }
99
+ s.pack('Q*')
100
+ end
101
+ singleton_class.send(:private, :xor!)
102
+
103
+ def increment_counter!
104
+ c = @counter_len
105
+ while ((c -= 1) > 0)
106
+ if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0
107
+ break
108
+ end
109
+ end
110
+ end
111
+ singleton_class.send(:private, :increment_counter!)
112
+ }
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,207 @@
1
+ require 'net/ssh/loggable'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ ## Extension module for aes(128|256)gcm ciphers
7
+ module GCMCipher
8
+ # rubocop:disable Metrics/AbcSize
9
+ def self.extended(orig)
10
+ # rubocop:disable Metrics/BlockLength
11
+ orig.class_eval do
12
+ include Net::SSH::Loggable
13
+
14
+ attr_reader :cipher
15
+ attr_reader :key
16
+ attr_reader :nonce
17
+
18
+ #
19
+ # Semantically gcm cipher supplies the OpenSSL iv interface with a nonce
20
+ # as it is not randomly generated due to being supplied from a counter.
21
+ # The RFC's use IV and nonce interchangeably.
22
+ #
23
+ def initialize(encrypt:, key:)
24
+ @cipher = OpenSSL::Cipher.new(algo_name)
25
+ @key = key
26
+ key_len = @cipher.key_len
27
+ if key.size != key_len
28
+ error_message = "#{cipher_name}: keylength does not match"
29
+ error { error_message }
30
+ raise error_message
31
+ end
32
+ encrypt ? @cipher.encrypt : @cipher.decrypt
33
+ @cipher.key = key
34
+
35
+ @nonce = {
36
+ fixed: nil,
37
+ invocation_counter: 0
38
+ }
39
+ end
40
+
41
+ def update_cipher_mac(payload, _sequence_number)
42
+ #
43
+ # --- RFC 5647 7.3 ---
44
+ # When using AES-GCM with secure shell, the packet_length field is to
45
+ # be treated as additional authenticated data, not as plaintext.
46
+ #
47
+ length_data = [payload.bytesize].pack('N')
48
+
49
+ cipher.auth_data = length_data
50
+
51
+ encrypted_data = cipher.update(payload) << cipher.final
52
+
53
+ mac = cipher.auth_tag
54
+
55
+ incr_nonce
56
+ length_data + encrypted_data + mac
57
+ end
58
+
59
+ #
60
+ # --- RFC 5647 ---
61
+ # uint32 packet_length; // 0 <= packet_length < 2^32
62
+ #
63
+ def read_length(data, _sequence_number)
64
+ data.unpack1('N')
65
+ end
66
+
67
+ #
68
+ # --- RFC 5647 ---
69
+ # In AES-GCM secure shell, the inputs to the authenticated encryption
70
+ # are:
71
+ # PT (Plain Text)
72
+ # byte padding_length; // 4 <= padding_length < 256
73
+ # byte[n1] payload; // n1 = packet_length-padding_length-1
74
+ # byte[n2] random_padding; // n2 = padding_length
75
+ # AAD (Additional Authenticated Data)
76
+ # uint32 packet_length; // 0 <= packet_length < 2^32
77
+ # IV (Initialization Vector)
78
+ # As described in section 7.1.
79
+ # BK (Block Cipher Key)
80
+ # The appropriate Encryption Key formed during the Key Exchange.
81
+ #
82
+ def read_and_mac(data, mac, _sequence_number)
83
+ # The authentication tag will be placed in the MAC field at the end of the packet
84
+
85
+ # OpenSSL does not verify auth tag length
86
+ # GCM mode allows arbitrary sizes for the auth_tag up to 128 bytes and a single
87
+ # byte allows authentication to pass. If single byte auth tags are possible
88
+ # an attacker would require no more than 256 attempts to forge a valid tag.
89
+ #
90
+ raise 'incorrect auth_tag length' unless mac.to_s.length == mac_length
91
+
92
+ packet_length = data.unpack1('N')
93
+
94
+ cipher.auth_tag = mac.to_s
95
+ cipher.auth_data = [packet_length].pack('N')
96
+
97
+ result = cipher.update(data[4...]) << cipher.final
98
+ incr_nonce
99
+ result
100
+ end
101
+
102
+ def mac_length
103
+ 16
104
+ end
105
+
106
+ def block_size
107
+ 16
108
+ end
109
+
110
+ def self.block_size
111
+ 16
112
+ end
113
+
114
+ #
115
+ # --- RFC 5647 ---
116
+ # N_MIN minimum nonce (IV) length 12 octets
117
+ # N_MAX maximum nonce (IV) length 12 octets
118
+ #
119
+ def iv_len
120
+ 12
121
+ end
122
+
123
+ #
124
+ # --- RFC 5288 ---
125
+ # Each value of the nonce_explicit MUST be distinct for each distinct
126
+ # invocation of the GCM encrypt function for any fixed key. Failure to
127
+ # meet this uniqueness requirement can significantly degrade security.
128
+ # The nonce_explicit MAY be the 64-bit sequence number.
129
+ #
130
+ # --- RFC 5116 ---
131
+ # (2.1) Applications that can generate distinct nonces SHOULD use the nonce
132
+ # formation method defined in Section 3.2, and MAY use any
133
+ # other method that meets the uniqueness requirement.
134
+ #
135
+ # (3.2) The following method to construct nonces is RECOMMENDED.
136
+ #
137
+ # <- variable -> <- variable ->
138
+ # - - - - - - - - - - - - - -
139
+ # | fixed | counter |
140
+ #
141
+ # Initial octets consist of a fixed field and final octets consist of a
142
+ # Counter field. Implementations SHOULD support 12-octet nonces in which
143
+ # the Counter field is four octets long.
144
+ # The Counter fields of successive nonces form a monotonically increasing
145
+ # sequence, when those fields are regarded as unsignd integers in network
146
+ # byte order.
147
+ # The Counter part SHOULD be equal to zero for the first nonce and increment
148
+ # by one for each successive nonce that is generated.
149
+ # The Fixed field MUST remain constant for all nonces that are generated for
150
+ # a given encryption device.
151
+ #
152
+ # --- RFC 5647 ---
153
+ # The invocation field is treated as a 64-bit integer and is increment after
154
+ # each invocation of AES-GCM to process a binary packet.
155
+ # AES-GCM produces a keystream in blocks of 16-octets that is used to
156
+ # encrypt the plaintext. This keystream is produced by encrypting the
157
+ # following 16-octet data structure:
158
+ #
159
+ # uint32 fixed; // 4 octets
160
+ # uint64 invocation_counter; // 8 octets
161
+ # unit32 block_counter; // 4 octets
162
+ #
163
+ # The block_counter is initially set to one (1) and increment as each block
164
+ # of key is produced.
165
+ #
166
+ # The reader is reminded that SSH requires that the data to be encrypted
167
+ # MUST be padded out to a multiple of the block size (16-octets for AES-GCM).
168
+ #
169
+ def incr_nonce
170
+ return if nonce[:fixed].nil?
171
+
172
+ nonce[:invocation_counter] = [nonce[:invocation_counter].to_s.unpack1('B*').to_i(2) + 1].pack('Q>*')
173
+
174
+ apply_nonce
175
+ end
176
+
177
+ def nonce=(iv_s)
178
+ return if nonce[:fixed]
179
+
180
+ nonce[:fixed] = iv_s[0...4]
181
+ nonce[:invocation_counter] = iv_s[4...12]
182
+
183
+ apply_nonce
184
+ end
185
+
186
+ def apply_nonce
187
+ cipher.iv = "#{nonce[:fixed]}#{nonce[:invocation_counter]}"
188
+ end
189
+
190
+ #
191
+ # --- RFC 5647 ---
192
+ # If AES-GCM is selected as the encryption algorithm for a given
193
+ # tunnel, AES-GCM MUST also be selected as the Message Authentication
194
+ # Code (MAC) algorithm. Conversely, if AES-GCM is selected as the MAC
195
+ # algorithm, it MUST also be selected as the encryption algorithm.
196
+ #
197
+ def implicit_mac?
198
+ true
199
+ end
200
+ end
201
+ end
202
+ # rubocop:enable Metrics/BlockLength
203
+ end
204
+ # rubocop:enable Metrics/AbcSize
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,113 @@
1
+ require 'openssl'
2
+ require 'openssl/digest'
3
+
4
+ module Net
5
+ module SSH
6
+ module Transport
7
+ module HMAC
8
+ # The base class of all OpenSSL-based HMAC algorithm wrappers.
9
+ class Abstract
10
+ class << self
11
+ def aead(*v)
12
+ @aead = false if !defined?(@aead)
13
+ if v.empty?
14
+ @aead = superclass.aead if @aead.nil? && superclass.respond_to?(:aead)
15
+ return @aead
16
+ elsif v.length == 1
17
+ @aead = v.first
18
+ else
19
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
20
+ end
21
+ end
22
+
23
+ def etm(*v)
24
+ @etm = false if !defined?(@etm)
25
+ if v.empty?
26
+ @etm = superclass.etm if @etm.nil? && superclass.respond_to?(:etm)
27
+ return @etm
28
+ elsif v.length == 1
29
+ @etm = v.first
30
+ else
31
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
32
+ end
33
+ end
34
+
35
+ def key_length(*v)
36
+ @key_length = nil if !defined?(@key_length)
37
+ if v.empty?
38
+ @key_length = superclass.key_length if @key_length.nil? && superclass.respond_to?(:key_length)
39
+ return @key_length
40
+ elsif v.length == 1
41
+ @key_length = v.first
42
+ else
43
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
44
+ end
45
+ end
46
+
47
+ def mac_length(*v)
48
+ @mac_length = nil if !defined?(@mac_length)
49
+ if v.empty?
50
+ @mac_length = superclass.mac_length if @mac_length.nil? && superclass.respond_to?(:mac_length)
51
+ return @mac_length
52
+ elsif v.length == 1
53
+ @mac_length = v.first
54
+ else
55
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
56
+ end
57
+ end
58
+
59
+ def digest_class(*v)
60
+ @digest_class = nil if !defined?(@digest_class)
61
+ if v.empty?
62
+ @digest_class = superclass.digest_class if @digest_class.nil? && superclass.respond_to?(:digest_class)
63
+ return @digest_class
64
+ elsif v.length == 1
65
+ @digest_class = v.first
66
+ else
67
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
68
+ end
69
+ end
70
+ end
71
+
72
+ def aead
73
+ self.class.aead
74
+ end
75
+
76
+ def etm
77
+ self.class.etm
78
+ end
79
+
80
+ def key_length
81
+ self.class.key_length
82
+ end
83
+
84
+ def mac_length
85
+ self.class.mac_length
86
+ end
87
+
88
+ def digest_class
89
+ self.class.digest_class
90
+ end
91
+
92
+ # The key in use for this instance.
93
+ attr_reader :key
94
+
95
+ def initialize(key = nil)
96
+ self.key = key
97
+ end
98
+
99
+ # Sets the key to the given value, truncating it so that it is the correct
100
+ # length.
101
+ def key=(value)
102
+ @key = value ? value.to_s[0, key_length] : nil
103
+ end
104
+
105
+ # Compute the HMAC digest for the given data string.
106
+ def digest(data)
107
+ OpenSSL::HMAC.digest(digest_class.new, key, data)[0, mac_length]
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,10 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The MD5 HMAC algorithm.
5
+ class MD5 < Abstract
6
+ mac_length 16
7
+ key_length 16
8
+ digest_class OpenSSL::Digest::MD5
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'net/ssh/transport/hmac/md5'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The MD5-96 HMAC algorithm. This returns only the first 12 bytes of
5
+ # the digest.
6
+ class MD5_96 < MD5
7
+ mac_length 12
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The "none" algorithm. This has a key and mac length of 0.
5
+ class None < Abstract
6
+ key_length 0
7
+ mac_length 0
8
+
9
+ def digest(data)
10
+ ""
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The RIPEMD-160 HMAC algorithm. This has a mac and key length of 20, and
5
+ # uses the RIPEMD-160 digest algorithm.
6
+ class RIPEMD160 < Abstract
7
+ mac_length 20
8
+ key_length 20
9
+ digest_class OpenSSL::Digest::RIPEMD160
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA1 HMAC algorithm. This has a mac and key length of 20, and
5
+ # uses the SHA1 digest algorithm.
6
+ class SHA1 < Abstract
7
+ mac_length 20
8
+ key_length 20
9
+ digest_class OpenSSL::Digest::SHA1
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'net/ssh/transport/hmac/sha1'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA1-96 HMAC algorithm. This returns only the first 12 bytes of
5
+ # the digest.
6
+ class SHA1_96 < SHA1
7
+ mac_length 12
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
5
+ # uses the SHA-256 digest algorithm.
6
+ class SHA2_256 < Abstract
7
+ mac_length 32
8
+ key_length 32
9
+ digest_class OpenSSL::Digest::SHA256
10
+ end
11
+ end