Class: Tem::SecPack

Inherits:
Object
  • Object
show all
Defined in:
lib/tem/secpack.rb

Constant Summary collapse

@@serialized_ivars =
[:body, :labels, :ep, :sp, :extra_bytes, :signed_bytes,
:encrypted_bytes, :bound, :lines]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ SecPack

Returns a new instance of SecPack.



43
44
45
46
47
48
49
# File 'lib/tem/secpack.rb', line 43

def initialize(args)
  @@serialized_ivars.map { |m| self.instance_variable_set :"@#{m}", args[m] }
  @bound ||= false
  
  @extra_bytes ||= 0
  # trim_extra_bytes if @extra_bytes == 0
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



26
27
28
# File 'lib/tem/secpack.rb', line 26

def body
  @body
end

#boundObject (readonly)

Returns the value of attribute bound.



26
27
28
# File 'lib/tem/secpack.rb', line 26

def bound
  @bound
end

#linesObject (readonly)

Returns the value of attribute lines.



27
28
29
# File 'lib/tem/secpack.rb', line 27

def lines
  @lines
end

Class Method Details

.new_from_array(array) ⇒ Object



7
8
9
10
11
# File 'lib/tem/secpack.rb', line 7

def self.new_from_array(array)
  arg_hash = { }
  @@serialized_ivars.each_with_index { |name, i| arg_hash[name] = array[i] }
  self.new arg_hash
end

.new_from_yaml_str(yaml_str) ⇒ Object



13
14
15
16
# File 'lib/tem/secpack.rb', line 13

def self.new_from_yaml_str(yaml_str)
  array = YAML.load yaml_str
  new_from_array array
end

Instance Method Details

#bind(public_key, encrypt_from = 0, plaintext_from = 0) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/tem/secpack.rb', line 55

def bind(public_key, encrypt_from = 0, plaintext_from = 0)
  expand_extra_bytes
  encrypt_from = @labels[encrypt_from.to_sym] unless encrypt_from.kind_of? Numeric
  plaintext_from = @labels[plaintext_from.to_sym] unless plaintext_from.kind_of? Numeric
  
  @signed_bytes = encrypt_from
  @encrypted_bytes = plaintext_from - encrypt_from
  
  secpack_sig = Tem::Abi.tem_hash [tem_header, @body[0...plaintext_from]].flatten
  crypt = public_key.encrypt [@body[encrypt_from...plaintext_from], secpack_sig].flatten
  @body = [@body[0...encrypt_from], crypt, @body[plaintext_from..-1]].flatten
    
  label_delta = crypt.length - @encrypted_bytes         
  @labels = Hash[*(@labels.map { |k, v|
    if v < encrypt_from
      [k, v] 
    elsif v < plaintext_from
      []
    else
      [k, v + label_delta]
    end
  }.flatten)]
  
  #trim_extra_bytes
  @bound = true
end

#expand_extra_bytesObject



38
39
40
41
# File 'lib/tem/secpack.rb', line 38

def expand_extra_bytes
  @body += [0] * @extra_bytes
  @extra_bytes = 0
end

#get_bytes(label, byte_count) ⇒ Object

Methods for interacting with the plaintext content of a SECpack.



117
118
119
120
121
122
123
# File 'lib/tem/secpack.rb', line 117

def get_bytes(label, byte_count)
  expand_extra_bytes
  raise "Unknown label #{label}" unless addr = @labels[label]
  bytes = @body[addr, byte_count]
  #trim_extra_bytes
  bytes
end

#get_value(label, abi_type) ⇒ Object



136
137
138
139
140
141
142
# File 'lib/tem/secpack.rb', line 136

def get_value(label, abi_type)
  expand_extra_bytes
  raise "Unknown label #{label}" unless addr = @labels[label]
  value = Tem::Abi.send :"read_#{abi_type}", @body, addr
  #trim_extra_bytes
  value
end

#label_address(label_name) ⇒ Object



51
52
53
# File 'lib/tem/secpack.rb', line 51

def label_address(label_name)
  @labels[label_name.to_sym]
end

#label_info_for_addr(addr) ⇒ Object



108
109
110
111
112
113
# File 'lib/tem/secpack.rb', line 108

def label_info_for_addr(addr)
  @labels.to_a.reverse_each do |info|
    return info.reverse if addr >= info[1]
  end
  return [0, :__start]
end

#line_info_for_addr(addr) ⇒ Object



97
98
99
100
101
102
103
104
105
106
# File 'lib/tem/secpack.rb', line 97

def line_info_for_addr(addr)
  return nil unless @lines

  @lines.reverse_each do |info|
    # If something breaks, it's likely to happen after the opcode of the 
    # offending instruction has been read, so assume offending_ip < ip.
    return info if addr >= info[0]
  end
  return @lines.first
end

#set_bytes(label, bytes) ⇒ Object



125
126
127
128
129
130
# File 'lib/tem/secpack.rb', line 125

def set_bytes(label, bytes)
  expand_extra_bytes
  raise "Unknown label #{label}" unless addr = @labels[label]
  @body[addr, bytes.length] = bytes
  #trim_extra_bytes
end

#set_value(label, abi_type, value) ⇒ Object



132
133
134
# File 'lib/tem/secpack.rb', line 132

def set_value(label, abi_type, value)
  set_bytes label, Tem::Abi.send(:"to_#{abi_type}", value)
end

#tem_formatted_bodyObject



91
92
93
94
95
# File 'lib/tem/secpack.rb', line 91

def tem_formatted_body
  # HACK: Ideally, we would allocate a bigger buffer, and then only fill part
  #       of it. Realistically, we'll just send in extra_bytes 0s.
  [tem_header, @body, [0] * @extra_bytes].flatten
end

#to_arrayObject



18
19
20
# File 'lib/tem/secpack.rb', line 18

def to_array
  @@serialized_ivars.map { |m| self.instance_variable_get :"@#{m}" }
end

#to_yaml_strObject



22
23
24
# File 'lib/tem/secpack.rb', line 22

def to_yaml_str
  self.to_array.to_yaml.to_s
end

#trim_extra_bytesObject



29
30
31
32
33
34
35
36
# File 'lib/tem/secpack.rb', line 29

def trim_extra_bytes
  @extra_bytes = 0
  while @extra_bytes < @body.length
    break if @body[-@extra_bytes - 1] != 0
    @extra_bytes += 1
  end
  @body.slice! @body.length - @extra_bytes, @extra_bytes    
end