Skip to content

Commit

Permalink
chain cipher iv correctly from packet to packet
Browse files Browse the repository at this point in the history
  • Loading branch information
jamis committed Sep 6, 2008
1 parent ed912ab commit b09b86c
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 21 deletions.
4 changes: 2 additions & 2 deletions lib/net/ssh/transport/packet_stream.rb
Expand Up @@ -169,8 +169,8 @@ def if_needs_rekey?
# the states and generally prepares the object for use as a packet stream.
def initialize_ssh
@hints = {}
@server = State.new(self)
@client = State.new(self)
@server = State.new(self, :server)
@client = State.new(self, :client)
@packet = nil
initialize_buffered_io
end
Expand Down
47 changes: 29 additions & 18 deletions lib/net/ssh/transport/state.rb
Expand Up @@ -31,6 +31,12 @@ class State
# The number of data blocks processed since the last call to #reset!
attr_reader :blocks

# The cipher algorithm in use for this socket endpoint.
attr_reader :cipher

# The role that this state plays (either :client or :server)
attr_reader :role

# The maximum number of packets that this endpoint wants to process before
# needing a rekey.
attr_accessor :max_packets
Expand All @@ -45,15 +51,15 @@ class State

# Creates a new state object, belonging to the given socket. Initializes
# the algorithms to "none".
def initialize(socket)
def initialize(socket, role)
@socket = socket
@role = role
@sequence_number = @packets = @blocks = 0
@cipher = CipherFactory.get("none")
@hmac = HMAC.get("none")
@compression = nil
@compressor = @decompressor = nil
@next_iv = nil
@cipher_needs_reset = false
@next_iv = ""
end

# A convenience method for quickly setting multiple values in a single
Expand All @@ -65,25 +71,16 @@ def set(values)
reset!
end

# The cipher algorithm in use for this socket endpoint.
def cipher
if @cipher_needs_reset
@cipher.reset
@cipher.iv = @next_iv
@cipher_needs_reset = false
end

@cipher
end

def update_cipher(data)
@next_iv = data[-cipher.iv_len..-1]
cipher.update(data)
result = cipher.update(data)
update_next_iv(role == :client ? result : data)
return result
end

def final_cipher
@cipher_needs_reset = true
cipher.final
result = cipher.final
update_next_iv(role == :client ? result : "", true)
return result
end

# Increments the counters. The sequence number is incremented (and remapped
Expand Down Expand Up @@ -185,6 +182,20 @@ def needs_rekey?
max_packets && packets > max_packets ||
max_blocks && blocks > max_blocks
end

private

def update_next_iv(data, reset=false)
@next_iv << data
@next_iv = @next_iv[-cipher.iv_len..-1]

if reset
cipher.reset
cipher.iv = @next_iv
end

return data
end
end

end; end; end
2 changes: 1 addition & 1 deletion test/transport/test_state.rb
Expand Up @@ -166,7 +166,7 @@ def socket
end

def state
@state ||= Net::SSH::Transport::State.new(socket)
@state ||= Net::SSH::Transport::State.new(socket, :test)
end
end

Expand Down

0 comments on commit b09b86c

Please sign in to comment.