summaryrefslogtreecommitdiff
path: root/lib/net/ssh/transport/packet_stream.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/net/ssh/transport/packet_stream.rb')
-rw-r--r--lib/net/ssh/transport/packet_stream.rb90
1 files changed, 57 insertions, 33 deletions
diff --git a/lib/net/ssh/transport/packet_stream.rb b/lib/net/ssh/transport/packet_stream.rb
index a4120d4..9466096 100644
--- a/lib/net/ssh/transport/packet_stream.rb
+++ b/lib/net/ssh/transport/packet_stream.rb
@@ -144,31 +144,36 @@ module Net
padding = Array.new(padding_length) { rand(256) }.pack("C*")
- if client.hmac.etm
- debug { "using encrypt-then-mac" }
+ if client.cipher.name == "chacha20-poly1305@openssh.com"
+ unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
+ message = client.cipher.update_cipher_mac(unencrypted_data, client.sequence_number)
+ else
+ if client.hmac.etm
+ debug { "using encrypt-then-mac" }
- # Encrypt padding_length, payload, and padding. Take MAC
- # from the unencrypted packet_lenght and the encrypted
- # data.
- length_data = [packet_length].pack("N")
+ # Encrypt padding_length, payload, and padding. Take MAC
+ # from the unencrypted packet_lenght and the encrypted
+ # data.
+ length_data = [packet_length].pack("N")
- unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
+ unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
- encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
+ encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
- mac_data = length_data + encrypted_data
+ mac_data = length_data + encrypted_data
- mac = client.hmac.digest([client.sequence_number, mac_data].pack("NA*"))
+ mac = client.hmac.digest([client.sequence_number, mac_data].pack("NA*"))
- message = mac_data + mac
- else
- unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*")
+ message = mac_data + mac
+ else
+ unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*")
- mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*"))
+ mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*"))
- encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
+ encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
- message = encrypted_data + mac
+ message = encrypted_data + mac
+ end
end
debug { "queueing packet nr #{client.sequence_number} type #{payload.getbyte(0)} len #{packet_length}" }
@@ -225,44 +230,63 @@ module Net
data = read_available(minimum + aad_length)
# decipher it
- if server.hmac.etm
- @packet_length = data.unpack("N").first
+ if server.cipher.name == "chacha20-poly1305@openssh.com"
+ @packet_length = server.cipher.read_length(data[0...4], server.sequence_number)
+ @packet = Net::SSH::Buffer.new()
@mac_data = data
- @packet = Net::SSH::Buffer.new(server.update_cipher(data[aad_length..-1]))
else
- @packet = Net::SSH::Buffer.new(server.update_cipher(data))
- @packet_length = @packet.read_long
+ if server.hmac.etm
+ @packet_length = data.unpack("N").first
+ @mac_data = data
+ @packet = Net::SSH::Buffer.new(server.update_cipher(data[aad_length..-1]))
+ else
+ @packet = Net::SSH::Buffer.new(server.update_cipher(data))
+ @packet_length = @packet.read_long
+ end
end
end
need = @packet_length + 4 - aad_length - server.block_size
raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0
- return nil if available < need + server.hmac.mac_length
+ if server.cipher.name == "chacha20-poly1305@openssh.com"
+ return nil if available < need + server.cipher.mac_length
+ else
+ return nil if available < need + server.hmac.mac_length
+ end
if need > 0
# read the remainder of the packet and decrypt it.
data = read_available(need)
- @mac_data += data if server.hmac.etm
- @packet.append(server.update_cipher(data))
+ @mac_data += data if server.hmac.etm || (server.cipher.name == "chacha20-poly1305@openssh.com")
+ if server.cipher.name != "chacha20-poly1305@openssh.com"
+ @packet.append(server.update_cipher(data))
+ end
end
- # get the hmac from the tail of the packet (if one exists), and
- # then validate it.
- real_hmac = read_available(server.hmac.mac_length) || ""
+ if server.cipher.name != "chacha20-poly1305@openssh.com"
+ # get the hmac from the tail of the packet (if one exists), and
+ # then validate it.
+ real_hmac = read_available(server.hmac.mac_length) || ""
- @packet.append(server.final_cipher)
- padding_length = @packet.read_byte
+ @packet.append(server.final_cipher)
+ padding_length = @packet.read_byte
- payload = @packet.read(@packet_length - padding_length - 1)
+ payload = @packet.read(@packet_length - padding_length - 1)
+
- my_computed_hmac = if server.hmac.etm
+ my_computed_hmac = if server.hmac.etm
server.hmac.digest([server.sequence_number, @mac_data].pack("NA*"))
else
server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
end
- raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
-
+ raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
+ else
+ real_hmac = read_available(server.cipher.mac_length) || ""
+ @packet = Net::SSH::Buffer.new(server.cipher.read_and_mac(@mac_data, real_hmac, server.sequence_number))
+ padding_length = @packet.read_byte
+ payload = @packet.read(@packet_length - padding_length - 1)
+ end
# try to decompress the payload, in case compression is active
payload = server.decompress(payload)