costan-tem_ruby 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +45 -0
- data/LICENSE +21 -0
- data/Manifest +75 -0
- data/README +8 -0
- data/Rakefile +23 -0
- data/bin/tem_bench +9 -0
- data/bin/tem_ca +13 -0
- data/bin/tem_irb +11 -0
- data/bin/tem_proxy +65 -0
- data/bin/tem_stat +35 -0
- data/dev_ca/ca_cert.cer +0 -0
- data/dev_ca/ca_cert.pem +32 -0
- data/dev_ca/ca_key.pem +27 -0
- data/dev_ca/config.yml +14 -0
- data/lib/tem/_cert.rb +158 -0
- data/lib/tem/apdus/buffers.rb +89 -0
- data/lib/tem/apdus/keys.rb +64 -0
- data/lib/tem/apdus/lifecycle.rb +13 -0
- data/lib/tem/apdus/tag.rb +38 -0
- data/lib/tem/auto_conf.rb +25 -0
- data/lib/tem/builders/abi.rb +482 -0
- data/lib/tem/builders/assembler.rb +314 -0
- data/lib/tem/builders/crypto.rb +124 -0
- data/lib/tem/builders/isa.rb +120 -0
- data/lib/tem/ca.rb +114 -0
- data/lib/tem/definitions/abi.rb +65 -0
- data/lib/tem/definitions/assembler.rb +23 -0
- data/lib/tem/definitions/isa.rb +188 -0
- data/lib/tem/ecert.rb +77 -0
- data/lib/tem/hive.rb +18 -0
- data/lib/tem/keys/asymmetric.rb +116 -0
- data/lib/tem/keys/key.rb +48 -0
- data/lib/tem/keys/symmetric.rb +47 -0
- data/lib/tem/sec_exec_error.rb +63 -0
- data/lib/tem/seclosures.rb +81 -0
- data/lib/tem/secpack.rb +107 -0
- data/lib/tem/tem.rb +31 -0
- data/lib/tem/toolkit.rb +101 -0
- data/lib/tem/transport/auto_configurator.rb +87 -0
- data/lib/tem/transport/java_card_mixin.rb +99 -0
- data/lib/tem/transport/jcop_remote_protocol.rb +59 -0
- data/lib/tem/transport/jcop_remote_server.rb +171 -0
- data/lib/tem/transport/jcop_remote_transport.rb +65 -0
- data/lib/tem/transport/pcsc_transport.rb +87 -0
- data/lib/tem/transport/transport.rb +10 -0
- data/lib/tem_ruby.rb +47 -0
- data/tem_ruby.gemspec +35 -0
- data/test/_test_cert.rb +70 -0
- data/test/builders/test_abi_builder.rb +298 -0
- data/test/tem_test_case.rb +26 -0
- data/test/tem_unit/test_tem_alu.rb +33 -0
- data/test/tem_unit/test_tem_bound_secpack.rb +51 -0
- data/test/tem_unit/test_tem_branching.rb +56 -0
- data/test/tem_unit/test_tem_crypto_asymmetric.rb +123 -0
- data/test/tem_unit/test_tem_crypto_hash.rb +35 -0
- data/test/tem_unit/test_tem_crypto_pstore.rb +53 -0
- data/test/tem_unit/test_tem_crypto_random.rb +25 -0
- data/test/tem_unit/test_tem_emit.rb +23 -0
- data/test/tem_unit/test_tem_memory.rb +48 -0
- data/test/tem_unit/test_tem_memory_compare.rb +65 -0
- data/test/tem_unit/test_tem_output.rb +32 -0
- data/test/tem_unit/test_tem_yaml_secpack.rb +47 -0
- data/test/test_driver.rb +108 -0
- data/test/test_exceptions.rb +35 -0
- data/test/transport/test_auto_configurator.rb +114 -0
- data/test/transport/test_java_card_mixin.rb +90 -0
- data/test/transport/test_jcop_remote.rb +82 -0
- data/timings/blank_bound_secpack.rb +18 -0
- data/timings/blank_sec.rb +14 -0
- data/timings/devchip_decrypt.rb +9 -0
- data/timings/post_buffer.rb +10 -0
- data/timings/simple_apdu.rb +5 -0
- data/timings/timings.rb +64 -0
- data/timings/vm_perf.rb +140 -0
- data/timings/vm_perf_bound.rb +141 -0
- metadata +201 -0
data/lib/tem/hive.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
# The TEM's configuation hive
|
5
|
+
module Tem::Hive
|
6
|
+
@@hive_dir = File.join(Gem.user_home, ".tem")
|
7
|
+
|
8
|
+
def self.path_to(*hive_entry)
|
9
|
+
File.join(@@hive_dir, *hive_entry)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(*hive_entry)
|
13
|
+
path = File.join(@@hive_dir, *hive_entry)
|
14
|
+
FileUtils.mkdir_p File.dirname(path)
|
15
|
+
File.open(path, "w") { |f| }
|
16
|
+
return path
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
module Tem::Keys
|
3
|
+
|
4
|
+
# Wraps a TEM asymmetric key, e.g. an RSA key.
|
5
|
+
class Asymmetric < Tem::Key
|
6
|
+
def self.new_from_array(array)
|
7
|
+
self.new(OpenSSL::PKey::RSA.new(array[0]), *array[1..-1])
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.new_from_yaml_str(yaml_str)
|
11
|
+
array = YAML.load yaml_str
|
12
|
+
new_from_array array
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_array
|
16
|
+
[@ssl_key.to_pem, @padding_type]
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_yaml_str
|
20
|
+
self.to_array.to_yaml.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
# Generate a pair of asymmetric keys.
|
24
|
+
def self.generate_pair
|
25
|
+
ssl_key = OpenSSL::PKey::RSA.generate(2048, 65537)
|
26
|
+
new_pair_from_ssl_key ssl_key
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates a pair of asymmetric keys wrapping an OpenSSL private key.
|
30
|
+
def self.new_pair_from_ssl_key(ssl_key)
|
31
|
+
{ :public => Tem::Keys::Asymmetric.new(ssl_key.public_key),
|
32
|
+
:private => Tem::Keys::Asymmetric.new(ssl_key) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(ssl_key, padding_type = :pkcs1)
|
36
|
+
super ssl_key
|
37
|
+
@is_public = !ssl_key.d
|
38
|
+
@padding_type = padding_type
|
39
|
+
|
40
|
+
case padding_type
|
41
|
+
when :oaep
|
42
|
+
@padding_id = OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
|
43
|
+
@padding_bytes = 42
|
44
|
+
when :pkcs1
|
45
|
+
@padding_id = OpenSSL::PKey::RSA::PKCS1_PADDING
|
46
|
+
@padding_bytes = 11
|
47
|
+
else
|
48
|
+
raise "Unknown padding type #{padding_type}\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
@size = 0
|
52
|
+
n = @is_public ? @ssl_key.n : (@ssl_key.p * @ssl_key.q)
|
53
|
+
while n != 0 do
|
54
|
+
@size += 1
|
55
|
+
n >>= 8
|
56
|
+
end
|
57
|
+
end
|
58
|
+
public_class_method :new
|
59
|
+
|
60
|
+
def is_public?
|
61
|
+
@is_public
|
62
|
+
end
|
63
|
+
|
64
|
+
def encrypt(data)
|
65
|
+
encrypt_or_decrypt data, @size - @padding_bytes,
|
66
|
+
@is_public ? :public_encrypt : :private_encrypt
|
67
|
+
end
|
68
|
+
|
69
|
+
def decrypt(data)
|
70
|
+
encrypt_or_decrypt data, @size,
|
71
|
+
@is_public ? :public_decrypt : :private_decrypt
|
72
|
+
end
|
73
|
+
|
74
|
+
def sign(data)
|
75
|
+
data = data.pack 'C*' if data.respond_to? :pack
|
76
|
+
# PKCS1-padding is forced in by openssl... sigh!
|
77
|
+
out_data = @ssl_key.sign OpenSSL::Digest::SHA1.new, data
|
78
|
+
data.respond_to?(:pack) ? out_data : out_data.unpack('C*')
|
79
|
+
end
|
80
|
+
|
81
|
+
def verify(data, signature)
|
82
|
+
data = data.pack 'C*' if data.respond_to? :pack
|
83
|
+
signature = signature.pack 'C*' if signature.respond_to? :pack
|
84
|
+
# PKCS1-padding is forced in by openssl... sigh!
|
85
|
+
@ssl_key.verify OpenSSL::Digest::SHA1.new, signature, data
|
86
|
+
end
|
87
|
+
|
88
|
+
def encrypt_or_decrypt(data, in_size, op)
|
89
|
+
chug_data(data, in_size) { |block| @ssl_key.send op, block, @padding_id }
|
90
|
+
end
|
91
|
+
private :encrypt_or_decrypt
|
92
|
+
|
93
|
+
def chug_data(data, in_size, &chug_block)
|
94
|
+
output = data.class.new
|
95
|
+
i = 0
|
96
|
+
while i < data.length do
|
97
|
+
block_size = (data.length - i < in_size) ? data.length - i : in_size
|
98
|
+
if data.kind_of? String
|
99
|
+
block = data[i...(i+block_size)]
|
100
|
+
else
|
101
|
+
block = data[i...(i+block_size)].pack('C*')
|
102
|
+
end
|
103
|
+
o_block = yield block
|
104
|
+
if data.kind_of? String
|
105
|
+
output += o_block
|
106
|
+
else
|
107
|
+
output += o_block.unpack('C*')
|
108
|
+
end
|
109
|
+
i += block_size
|
110
|
+
end
|
111
|
+
return output
|
112
|
+
end
|
113
|
+
private :chug_data
|
114
|
+
end
|
115
|
+
|
116
|
+
end # namespace Tem::Keys
|
data/lib/tem/keys/key.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Base class for the TEM keys.
|
2
|
+
#
|
3
|
+
# This class consists of stubs describing the interface implemented by
|
4
|
+
# subclasses.
|
5
|
+
class Tem::Key
|
6
|
+
# The OpenSSL key wrapped by this TEM key.
|
7
|
+
attr_reader :ssl_key
|
8
|
+
|
9
|
+
# Creates a new key based on an OpenSSL key.
|
10
|
+
def initialize(ssl_key)
|
11
|
+
@ssl_key = ssl_key
|
12
|
+
end
|
13
|
+
# This class should not be instantiated directly.
|
14
|
+
private_class_method :new
|
15
|
+
|
16
|
+
# Serializes this key to the TEM ABI format.
|
17
|
+
def to_tem_key
|
18
|
+
Tem::Abi.to_tem_key self
|
19
|
+
end
|
20
|
+
|
21
|
+
# Encrypts a block of data into a TEM-friendly format.
|
22
|
+
def encrypt(data)
|
23
|
+
raise "TEM Key class #{self.class.name} didn't implement encrypt"
|
24
|
+
end
|
25
|
+
|
26
|
+
def decrypt(data)
|
27
|
+
raise "TEM Key class #{self.class.name} didn't implement decrypt"
|
28
|
+
end
|
29
|
+
|
30
|
+
def sign(data)
|
31
|
+
raise "TEM Key class #{self.class.name} didn't implement sign"
|
32
|
+
end
|
33
|
+
|
34
|
+
def verify(data)
|
35
|
+
raise "TEM Key class #{self.class.name} didn't implement verify"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a new TEM key wrapper from a SSL key
|
39
|
+
def self.new_from_ssl_key(ssl_key)
|
40
|
+
if ssl_key.kind_of? OpenSSL::PKey::PKey
|
41
|
+
Tem::Keys::Asymmetric.new ssl_key
|
42
|
+
elsif ssl_key.kind_of? OpenSSL::Cipher::Cipher
|
43
|
+
Tem::Keys::Symmetric.new ssl_key
|
44
|
+
else
|
45
|
+
raise "Can't handle keys of class #{ssl_key.class}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
module Tem::Keys
|
3
|
+
|
4
|
+
# Wraps a TEM symmetric key, e.g. an AES key.
|
5
|
+
class Symmetric < Tem::Key
|
6
|
+
@@cipher_mode = 'ECB'
|
7
|
+
|
8
|
+
# Generates a new symmetric key.
|
9
|
+
def self.generate
|
10
|
+
cipher = OpenSSL::Cipher::AES128.new @@cipher_mode
|
11
|
+
key = cipher.random_key
|
12
|
+
self.new key
|
13
|
+
end
|
14
|
+
|
15
|
+
# Creates a new symmetric key based on an OpenSSL Cipher instance, augmented
|
16
|
+
# with a key accessor.
|
17
|
+
def initialize(ssl_key)
|
18
|
+
super ssl_key
|
19
|
+
@key = ssl_key.key
|
20
|
+
@cipher_class = ssl_key.class
|
21
|
+
end
|
22
|
+
public_class_method :new
|
23
|
+
|
24
|
+
def encrypt_or_decrypt(data, do_encrypt)
|
25
|
+
cipher = @cipher_class.new @@cipher_mode
|
26
|
+
do_encrypt ? cipher.encrypt : cipher.decrypt
|
27
|
+
cipher.key = @key
|
28
|
+
cipher.iv = "\0" * 16
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def encrypt(data)
|
33
|
+
cipher.encrypt_or_decrypt data, true
|
34
|
+
end
|
35
|
+
|
36
|
+
def decrypt(data)
|
37
|
+
cipher.encrypt_or_decrypt data, false
|
38
|
+
end
|
39
|
+
|
40
|
+
def sign(data)
|
41
|
+
end
|
42
|
+
|
43
|
+
def verify(data)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end # namespace Tem::Keys
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# raised when executing a SEC
|
2
|
+
class Tem::SecExecError < StandardError
|
3
|
+
attr_reader :line_info
|
4
|
+
attr_reader :buffer_state, :key_state
|
5
|
+
attr_reader :trace
|
6
|
+
|
7
|
+
def initialize(line_info, tem_trace, buffer_state, key_state)
|
8
|
+
super 'SEC execution failed on the TEM'
|
9
|
+
@line_info = line_info
|
10
|
+
line_ip, atom, backtrace = *line_info
|
11
|
+
@atom = atom
|
12
|
+
if tem_trace and tem_trace[:ip]
|
13
|
+
@ip_delta = tem_trace[:ip] - line_ip
|
14
|
+
else
|
15
|
+
@ip_delta = 0
|
16
|
+
end
|
17
|
+
@trace = tem_trace
|
18
|
+
@buffer_state = buffer_state
|
19
|
+
@key_state = key_state
|
20
|
+
set_backtrace backtrace
|
21
|
+
end
|
22
|
+
|
23
|
+
def bstat_str
|
24
|
+
if @buffer_state.nil?
|
25
|
+
"no buffer state available"
|
26
|
+
else
|
27
|
+
@buffer_state.inspect
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def kstat_str
|
32
|
+
if @key_state.nil?
|
33
|
+
"no key state available"
|
34
|
+
else
|
35
|
+
@key_state.inspect
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def trace_str
|
40
|
+
if @trace.nil?
|
41
|
+
"no trace available"
|
42
|
+
else
|
43
|
+
"ip=#{'%04x' % @trace[:ip]} sp=#{'%04x' % @trace[:sp]} out=#{'%04x' % @trace[:out]} pscell=#{'%04x' % @trace[:pscell]}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
string = <<ENDSTRING
|
49
|
+
SECpack execution generated an exception on the TEM
|
50
|
+
|
51
|
+
TEM Trace: #{trace_str}
|
52
|
+
TEM Buffer Status:#{bstat_str}
|
53
|
+
TEM Key Status:#{kstat_str}
|
54
|
+
|
55
|
+
TEM execution error at #{@atom}+#{@ip_delta}
|
56
|
+
ENDSTRING
|
57
|
+
string.strip
|
58
|
+
end
|
59
|
+
|
60
|
+
def inspect
|
61
|
+
trace_str + "\n" + bstat_str + "\n" + kstat_str
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Tem::SeClosures
|
4
|
+
module MixedMethods
|
5
|
+
def assemble(&block)
|
6
|
+
return Tem::Assembler.assemble(&block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
include MixedMethods
|
11
|
+
def self.included(klass)
|
12
|
+
klass.extend MixedMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
def sec_trace
|
16
|
+
#begin
|
17
|
+
trace = @transport.applet_apdu! :ins => 0x54
|
18
|
+
if trace.length > 2
|
19
|
+
case read_tem_short(trace, 0) # trace version
|
20
|
+
when 1
|
21
|
+
return {:sp => read_tem_short(trace, 2), :ip => read_tem_short(trace, 4),
|
22
|
+
:out => read_tem_short(trace, 6), :pscell => read_tem_short(trace, 8)}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
return nil # unreadable trace
|
26
|
+
#rescue
|
27
|
+
# return nil
|
28
|
+
#end
|
29
|
+
end
|
30
|
+
|
31
|
+
def solve_psfault
|
32
|
+
# TODO: better strategy, lol
|
33
|
+
next_cell = rand(16)
|
34
|
+
@transport.applet_apdu! :ins => 0x53, :p12 => to_tem_ushort(next_cell)
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute(secpack, key_id = 0)
|
38
|
+
# load SECpack
|
39
|
+
buffer_id = post_buffer(secpack.tem_formatted_body)
|
40
|
+
response = @transport.applet_apdu! :ins => 0x50, :p1 => buffer_id,
|
41
|
+
:p2 => key_id
|
42
|
+
tem_secpack_error(response) if read_tem_byte(response, 0) != 1
|
43
|
+
|
44
|
+
# execute SEC
|
45
|
+
sec_exception = nil
|
46
|
+
loop do
|
47
|
+
response = @transport.applet_apdu! :ins => 0x52
|
48
|
+
sec_status = read_tem_byte(response, 0)
|
49
|
+
case sec_status
|
50
|
+
when 2 # success
|
51
|
+
break
|
52
|
+
when 3 # exception
|
53
|
+
# there is an exception, try to collect the trace
|
54
|
+
b_stat = stat_buffers() rescue nil
|
55
|
+
k_stat = stat_keys() rescue nil
|
56
|
+
trace = sec_trace()
|
57
|
+
if trace and trace[:ip]
|
58
|
+
line_info = secpack.line_info_for_ip(trace[:ip])
|
59
|
+
else
|
60
|
+
line_info = [0, :unknown, Kernel.caller]
|
61
|
+
end
|
62
|
+
sec_exception = Tem::SecExecError.new line_info, trace, b_stat, k_stat
|
63
|
+
break
|
64
|
+
when 4 # persistent store fault
|
65
|
+
solve_psfault
|
66
|
+
else
|
67
|
+
raise "Unrecognized execution engine status #{sec_status}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# unbind SEC
|
72
|
+
response = @transport.applet_apdu! :ins => 0x51
|
73
|
+
raise sec_exception if sec_exception
|
74
|
+
buffer_id = read_tem_byte(response, 0)
|
75
|
+
buffer_length = read_tem_short(response, 1)
|
76
|
+
data_buffer = read_buffer buffer_id
|
77
|
+
release_buffer buffer_id
|
78
|
+
|
79
|
+
return data_buffer[0...buffer_length]
|
80
|
+
end
|
81
|
+
end
|
data/lib/tem/secpack.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class Tem::SecPack
|
4
|
+
@@serialized_ivars = [:body, :labels, :ep, :sp, :extra_bytes, :signed_bytes,
|
5
|
+
:encrypted_bytes, :bound, :lines]
|
6
|
+
|
7
|
+
def self.new_from_array(array)
|
8
|
+
arg_hash = { }
|
9
|
+
@@serialized_ivars.each_with_index { |name, i| arg_hash[name] = array[i] }
|
10
|
+
self.new arg_hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.new_from_yaml_str(yaml_str)
|
14
|
+
array = YAML.load yaml_str
|
15
|
+
new_from_array array
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_array
|
19
|
+
@@serialized_ivars.map { |m| self.instance_variable_get :"@#{m}" }
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_yaml_str
|
23
|
+
self.to_array.to_yaml.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :body, :bound
|
27
|
+
attr_reader :lines
|
28
|
+
|
29
|
+
def trim_extra_bytes
|
30
|
+
@extra_bytes = 0
|
31
|
+
while @extra_bytes < @body.length
|
32
|
+
break if @body[-@extra_bytes - 1] != 0
|
33
|
+
@extra_bytes += 1
|
34
|
+
end
|
35
|
+
@body.slice! @body.length - @extra_bytes, @extra_bytes
|
36
|
+
end
|
37
|
+
|
38
|
+
def expand_extra_bytes
|
39
|
+
@body += [0] * @extra_bytes
|
40
|
+
@extra_bytes = 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(args)
|
44
|
+
@@serialized_ivars.map { |m| self.instance_variable_set :"@#{m}", args[m] }
|
45
|
+
@bound ||= false
|
46
|
+
|
47
|
+
@extra_bytes ||= 0
|
48
|
+
# trim_extra_bytes if @extra_bytes == 0
|
49
|
+
end
|
50
|
+
|
51
|
+
def label_address(label_name)
|
52
|
+
@labels[label_name.to_sym]
|
53
|
+
end
|
54
|
+
|
55
|
+
def bind(public_key, encrypt_from = 0, plaintext_from = 0)
|
56
|
+
expand_extra_bytes
|
57
|
+
encrypt_from = @labels[encrypt_from.to_sym] unless encrypt_from.kind_of? Numeric
|
58
|
+
plaintext_from = @labels[plaintext_from.to_sym] unless plaintext_from.kind_of? Numeric
|
59
|
+
|
60
|
+
@signed_bytes = encrypt_from
|
61
|
+
@encrypted_bytes = plaintext_from - encrypt_from
|
62
|
+
|
63
|
+
secpack_sig = Tem::Abi.tem_hash [tem_header, @body[0...plaintext_from]].flatten
|
64
|
+
crypt = public_key.encrypt [@body[encrypt_from...plaintext_from], secpack_sig].flatten
|
65
|
+
@body = [@body[0...encrypt_from], crypt, @body[plaintext_from..-1]].flatten
|
66
|
+
|
67
|
+
label_delta = crypt.length - @encrypted_bytes
|
68
|
+
@labels = Hash[*(@labels.map { |k, v|
|
69
|
+
if v < encrypt_from
|
70
|
+
[k, v]
|
71
|
+
elsif v < plaintext_from
|
72
|
+
[]
|
73
|
+
else
|
74
|
+
[k, v + label_delta]
|
75
|
+
end
|
76
|
+
}.flatten)]
|
77
|
+
|
78
|
+
#trim_extra_bytes
|
79
|
+
@bound = true
|
80
|
+
end
|
81
|
+
|
82
|
+
def tem_header
|
83
|
+
# TODO: use 0x0100 (no tracing) depending on options
|
84
|
+
hh = [0x0101, @signed_bytes || 0, @encrypted_bytes || 0, @extra_bytes, @sp,
|
85
|
+
@ep].map { |n| Tem::Abi.to_tem_ushort n }.flatten
|
86
|
+
hh += Array.new((Tem::Abi.tem_hash [0]).length - hh.length, 0)
|
87
|
+
return hh
|
88
|
+
end
|
89
|
+
private :tem_header
|
90
|
+
|
91
|
+
def tem_formatted_body
|
92
|
+
# HACK: Ideally, we would allocate a bigger buffer, and then only fill part
|
93
|
+
# of it. Realistically, we'll just send in extra_bytes 0s.
|
94
|
+
[tem_header, @body, [0] * @extra_bytes].flatten
|
95
|
+
end
|
96
|
+
|
97
|
+
def line_info_for_ip(ip)
|
98
|
+
return nil unless @lines
|
99
|
+
|
100
|
+
@lines.reverse_each do |info|
|
101
|
+
# If something breaks, it's likely to happen after the opcode of the
|
102
|
+
# offending instruction has been read, so assume offending_ip < ip.
|
103
|
+
return info if ip >= info[0]
|
104
|
+
end
|
105
|
+
return info.first
|
106
|
+
end
|
107
|
+
end
|