Class: Tem::SecPack
- Inherits:
-
Object
- Object
- Tem::SecPack
- Defined in:
- lib/tem/secpack.rb
Constant Summary collapse
- @@serialized_ivars =
[:body, :labels, :ep, :sp, :extra_bytes, :signed_bytes, :secret_bytes, :bound, :lines]
Instance Attribute Summary collapse
-
#body ⇒ Object
readonly
The SECpack’s body.
-
#bound ⇒ Object
readonly
The size of the encrypted data, if the SECpack is bound.
-
#lines ⇒ Object
readonly
Debugging information.
-
#secret_bytes ⇒ Object
readonly
The size of the secret data in the SECpack.
Class Method Summary collapse
Instance Method Summary collapse
- #bind(public_key, secret_from = :secret, plain_from = :plain) ⇒ Object
-
#copy ⇒ Object
Creates a deep copy of the SECpack.
-
#encrypted_data ⇒ Object
The encrypted data in a SECpack.
-
#encrypted_data=(new_encrypted_bytes) ⇒ Object
Replaces the encrypted bytes in a SECpack.
- #expand_extra_bytes ⇒ Object
- #fake_bind(secret_from = :secret, plain_from = :plain) ⇒ Object
-
#get_bytes(label, byte_count) ⇒ Object
Methods for interacting with the plaintext content of a SECpack.
- #get_value(label, abi_type) ⇒ Object
-
#initialize(args) ⇒ SecPack
constructor
A new instance of SecPack.
- #label_address(label_name) ⇒ Object
- #label_info_for_addr(addr) ⇒ Object
- #line_info_for_addr(addr) ⇒ Object
-
#relocate_labels(same_until, delete_until, delta) ⇒ Object
Relocates the labels to reflect a change in the size of encrypted bytes.
- #set_bytes(label, bytes) ⇒ Object
- #set_value(label, abi_type, value) ⇒ Object
- #tem_formatted_body ⇒ Object
- #to_array ⇒ Object
- #to_yaml_str ⇒ Object
- #trim_extra_bytes ⇒ Object
Constructor Details
#initialize(args) ⇒ SecPack
Returns a new instance of SecPack.
54 55 56 57 58 59 60 |
# File 'lib/tem/secpack.rb', line 54 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
#body ⇒ Object (readonly)
The SECpack’s body.
34 35 36 |
# File 'lib/tem/secpack.rb', line 34 def body @body end |
#bound ⇒ Object (readonly)
The size of the encrypted data, if the SECpack is bound. False otherwise.
36 37 38 |
# File 'lib/tem/secpack.rb', line 36 def bound @bound end |
#lines ⇒ Object (readonly)
Debugging information.
38 39 40 |
# File 'lib/tem/secpack.rb', line 38 def lines @lines end |
#secret_bytes ⇒ Object (readonly)
The size of the secret data in the SECpack.
32 33 34 |
# File 'lib/tem/secpack.rb', line 32 def secret_bytes @secret_bytes 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, secret_from = :secret, plain_from = :plain) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/tem/secpack.rb', line 66 def bind(public_key, secret_from = :secret, plain_from = :plain) raise "SECpack is already bound" if @bound unless secret_from.kind_of? Numeric secret_from_label = secret_from secret_from = @labels[secret_from.to_sym] raise "Undefined label #{secret_from_label}" unless secret_from end unless plain_from.kind_of? Numeric plain_from_label = plain_from plain_from = @labels[plain_from.to_sym] raise "Undefined label #{plain_from_label}" unless plain_from end @signed_bytes = secret_from @secret_bytes = plain_from - secret_from secpack_sig = Tem::Abi.tem_hash tem_header + @body[0, plain_from] crypt = public_key.encrypt @body[secret_from, @secret_bytes] + secpack_sig @body = [@body[0, secret_from], crypt, @body[plain_from..-1]].flatten label_delta = crypt.length - @secret_bytes relocate_labels secret_from, plain_from, label_delta #trim_extra_bytes @bound = crypt.length end |
#copy ⇒ Object
Creates a deep copy of the SECpack.
19 20 21 |
# File 'lib/tem/secpack.rb', line 19 def copy Tem::SecPack.new_from_yaml_str self.to_yaml_str end |
#encrypted_data ⇒ Object
The encrypted data in a SECpack.
This is useful for SECpack migration – the encrypted bytes are the only part that has to be migrated.
139 140 141 |
# File 'lib/tem/secpack.rb', line 139 def encrypted_data @body[@signed_bytes, @bound] end |
#encrypted_data=(new_encrypted_bytes) ⇒ Object
Replaces the encrypted bytes in a SECpack.
This is used in SECpack migration – the encryption bytes are the only part that changes during migration.
147 148 149 150 151 152 153 154 |
# File 'lib/tem/secpack.rb', line 147 def encrypted_data=(new_encrypted_bytes) raise "SECpack is not bound. See #bind and #fake_bind." unless @bound @body[@signed_bytes, @bound] = new_encrypted_bytes relocate_labels @signed_bytes, @signed_bytes + @bound, new_encrypted_bytes.length - @bound @bound = new_encrypted_bytes.length end |
#expand_extra_bytes ⇒ Object
49 50 51 52 |
# File 'lib/tem/secpack.rb', line 49 def @body += [0] * @extra_bytes @extra_bytes = 0 end |
#fake_bind(secret_from = :secret, plain_from = :plain) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/tem/secpack.rb', line 95 def fake_bind(secret_from = :secret, plain_from = :plain) raise "SECpack is already bound" if @bound unless secret_from.kind_of? Numeric secret_from_label = secret_from secret_from = @labels[secret_from.to_sym] raise "Undefined label #{secret_from_label}" unless secret_from end unless plain_from.kind_of? Numeric plain_from_label = plain_from plain_from = @labels[plain_from.to_sym] raise "Undefined label #{plain_from_label}" unless plain_from end @signed_bytes = secret_from @secret_bytes = plain_from - secret_from #trim_extra_bytes @bound = @secret_bytes end |
#get_bytes(label, byte_count) ⇒ Object
Methods for interacting with the plaintext content of a SECpack.
191 192 193 194 195 196 197 |
# File 'lib/tem/secpack.rb', line 191 def get_bytes(label, byte_count) raise "Unknown label #{label}" unless addr = @labels[label] bytes = @body[addr, byte_count] #trim_extra_bytes bytes end |
#get_value(label, abi_type) ⇒ Object
210 211 212 213 214 215 216 |
# File 'lib/tem/secpack.rb', line 210 def get_value(label, abi_type) 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
62 63 64 |
# File 'lib/tem/secpack.rb', line 62 def label_address(label_name) @labels[label_name.to_sym] end |
#label_info_for_addr(addr) ⇒ Object
182 183 184 185 186 187 |
# File 'lib/tem/secpack.rb', line 182 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
171 172 173 174 175 176 177 178 179 180 |
# File 'lib/tem/secpack.rb', line 171 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 |
#relocate_labels(same_until, delete_until, delta) ⇒ Object
Relocates the labels to reflect a change in the size of encrypted bytes.
Args:
same_until:: the end of the signed area (no relocations done there)
delete_until:: the end of the old encrypted area (labels are removed)
delta:: the size difference between the new and the old encrypted areas
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/tem/secpack.rb', line 123 def relocate_labels(same_until, delete_until, delta) @labels = Hash[*(@labels.map { |k, v| if v <= same_until [k, v] elsif v < delete_until [] else [k, v + delta] end }.flatten)] end |
#set_bytes(label, bytes) ⇒ Object
199 200 201 202 203 204 |
# File 'lib/tem/secpack.rb', line 199 def set_bytes(label, 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
206 207 208 |
# File 'lib/tem/secpack.rb', line 206 def set_value(label, abi_type, value) set_bytes label, Tem::Abi.send(:"to_#{abi_type}", value) end |
#tem_formatted_body ⇒ Object
165 166 167 168 169 |
# File 'lib/tem/secpack.rb', line 165 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_array ⇒ Object
23 24 25 |
# File 'lib/tem/secpack.rb', line 23 def to_array @@serialized_ivars.map { |m| self.instance_variable_get :"@#{m}" } end |
#to_yaml_str ⇒ Object
27 28 29 |
# File 'lib/tem/secpack.rb', line 27 def to_yaml_str self.to_array.to_yaml.to_s end |
#trim_extra_bytes ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/tem/secpack.rb', line 40 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 |