summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRyosuke Yamazaki <ryosuke.yamazaki@mac.com>2011-12-15 11:33:30 +0900
committerRyosuke Yamazaki <ryosuke.yamazaki@mac.com>2011-12-15 11:33:30 +0900
commit34af68b7f2726ed142c6b6f6b5704c1de562804e (patch)
tree29995127cfcb88e26585fccdc7d544cc080ef351 /lib
parent881d6217cc0a4093d815ac9ab0252733afd9eecc (diff)
downloadnet-ssh-34af68b7f2726ed142c6b6f6b5704c1de562804e.tar.gz
fix for hmac key deriving bug
Diffstat (limited to 'lib')
-rw-r--r--lib/net/ssh/transport/algorithms.rb10
-rw-r--r--lib/net/ssh/transport/hmac.rb40
2 files changed, 43 insertions, 7 deletions
diff --git a/lib/net/ssh/transport/algorithms.rb b/lib/net/ssh/transport/algorithms.rb
index 9c7f8d0..004a82b 100644
--- a/lib/net/ssh/transport/algorithms.rb
+++ b/lib/net/ssh/transport/algorithms.rb
@@ -28,7 +28,9 @@ module Net; module SSH; module Transport
:encryption => %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc
aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se
idea-cbc none arcfour128 arcfour256),
- :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 none),
+ :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96
+ hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96
+ hmac-sha2-512-96 none),
:compression => %w(none zlib@openssh.com zlib),
:language => %w()
}
@@ -351,8 +353,8 @@ module Net; module SSH; module Transport
cipher_client = CipherFactory.get(encryption_client, parameters.merge(:encrypt => true))
cipher_server = CipherFactory.get(encryption_server, parameters.merge(:iv => iv_server, :key => key_server, :decrypt => true))
- mac_client = HMAC.get(hmac_client, mac_key_client)
- mac_server = HMAC.get(hmac_server, mac_key_server)
+ mac_client = HMAC.get(hmac_client, mac_key_client, parameters)
+ mac_server = HMAC.get(hmac_server, mac_key_server, parameters)
session.configure_client :cipher => cipher_client, :hmac => mac_client,
:compression => normalize_compression_name(compression_client),
@@ -381,4 +383,4 @@ module Net; module SSH; module Transport
end
end
end
-end; end; end \ No newline at end of file
+end; end; end
diff --git a/lib/net/ssh/transport/hmac.rb b/lib/net/ssh/transport/hmac.rb
index 262db73..c2a79f4 100644
--- a/lib/net/ssh/transport/hmac.rb
+++ b/lib/net/ssh/transport/hmac.rb
@@ -2,6 +2,10 @@ require 'net/ssh/transport/hmac/md5'
require 'net/ssh/transport/hmac/md5_96'
require 'net/ssh/transport/hmac/sha1'
require 'net/ssh/transport/hmac/sha1_96'
+require 'net/ssh/transport/hmac/sha2_256'
+require 'net/ssh/transport/hmac/sha2_256_96'
+require 'net/ssh/transport/hmac/sha2_512'
+require 'net/ssh/transport/hmac/sha2_512_96'
require 'net/ssh/transport/hmac/none'
# Implements a simple factory interface for fetching hmac implementations, or
@@ -16,11 +20,19 @@ module Net::SSH::Transport::HMAC
'none' => None
}
+ # add mapping to sha2 hmac algorithms if they're available
+ MAP['hmac-sha2-256'] = SHA2_256 if defined?(::Net::SSH::Transport::HMAC::SHA2_256)
+ MAP['hmac-sha2-256-96'] = SHA2_256_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_256_96)
+ MAP['hmac-sha2-512'] = SHA2_512 if defined?(::Net::SSH::Transport::HMAC::SHA2_512)
+ MAP['hmac-sha2-512-96'] = SHA2_512_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_512_96)
+
# Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is
# given, the new instance will be initialized with that key.
- def self.get(name, key="")
+ def self.get(name, key="", parameters = {})
+ puts "digest key len: " + key.length.to_s
impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
- impl.new(key)
+
+ impl.new(make_key(impl.key_length, key, parameters))
end
# Retrieves the key length for the hmac of the given SSH type (+name+).
@@ -28,4 +40,26 @@ module Net::SSH::Transport::HMAC
impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
impl.key_length
end
-end \ No newline at end of file
+
+ # XXX copied
+ # Generate a key value in accordance with the SSH2 specification.
+ def self.make_key(bytes, start, options={})
+ if bytes == 0
+ return ""
+ end
+
+ k = start[0, bytes]
+
+ digester = options[:digester] or raise 'No digester supplied'
+ shared = options[:shared] or raise 'No shared secret supplied'
+ hash = options[:hash] or raise 'No hash supplied'
+
+ while k.length < bytes
+ step = digester.digest(shared + hash + k)
+ bytes_needed = bytes - k.length
+ k << step[0, bytes_needed]
+ end
+
+ return k
+ end
+end