tem_ruby 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +2 -0
  2. data/Manifest +17 -3
  3. data/lib/tem/apdus/buffers.rb +1 -2
  4. data/lib/tem/builders/abi.rb +2 -2
  5. data/lib/tem/builders/assembler.rb +314 -0
  6. data/lib/tem/builders/crypto.rb +17 -8
  7. data/lib/tem/builders/isa.rb +120 -0
  8. data/lib/tem/definitions/abi.rb +8 -10
  9. data/lib/tem/definitions/assembler.rb +23 -0
  10. data/lib/tem/definitions/isa.rb +188 -0
  11. data/lib/tem/ecert.rb +15 -16
  12. data/lib/tem/sec_exec_error.rb +21 -3
  13. data/lib/tem/seclosures.rb +9 -5
  14. data/lib/tem/secpack.rb +50 -30
  15. data/lib/tem/toolkit.rb +11 -15
  16. data/lib/tem/transport/jcop_remote_protocol.rb +10 -2
  17. data/lib/tem_ruby.rb +4 -2
  18. data/tem_ruby.gemspec +5 -5
  19. data/test/tem_unit/test_tem_alu.rb +33 -0
  20. data/test/tem_unit/test_tem_bound_secpack.rb +51 -0
  21. data/test/tem_unit/test_tem_branching.rb +56 -0
  22. data/test/tem_unit/test_tem_crypto_asymmetric.rb +123 -0
  23. data/test/tem_unit/test_tem_crypto_hash.rb +35 -0
  24. data/test/tem_unit/test_tem_crypto_pstore.rb +53 -0
  25. data/test/tem_unit/test_tem_crypto_random.rb +25 -0
  26. data/test/tem_unit/test_tem_emit.rb +23 -0
  27. data/test/tem_unit/test_tem_memory.rb +48 -0
  28. data/test/tem_unit/test_tem_memory_compare.rb +65 -0
  29. data/test/tem_unit/test_tem_output.rb +32 -0
  30. data/test/tem_unit/test_tem_yaml_secpack.rb +47 -0
  31. data/test/test_exceptions.rb +1 -2
  32. data/timings/blank_bound_secpack.rb +3 -5
  33. data/timings/blank_sec.rb +2 -3
  34. data/timings/timings.rb +7 -2
  35. data/timings/vm_perf.rb +9 -10
  36. data/timings/vm_perf_bound.rb +9 -10
  37. metadata +35 -9
  38. data/lib/tem/sec_assembler.rb +0 -90
  39. data/lib/tem/sec_opcodes.rb +0 -154
  40. data/test/test_tem.rb +0 -524
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.10.2. More internal refactorings.
2
+
1
3
  v0.10.1. Internal refactorings.
2
4
 
3
5
  v0.10.0. New transport code, allowing for multiple readers and TEM proxying.
data/Manifest CHANGED
@@ -15,17 +15,19 @@ lib/tem/apdus/lifecycle.rb
15
15
  lib/tem/apdus/tag.rb
16
16
  lib/tem/auto_conf.rb
17
17
  lib/tem/builders/abi.rb
18
+ lib/tem/builders/assembler.rb
18
19
  lib/tem/builders/crypto.rb
20
+ lib/tem/builders/isa.rb
19
21
  lib/tem/ca.rb
20
22
  lib/tem/definitions/abi.rb
23
+ lib/tem/definitions/assembler.rb
24
+ lib/tem/definitions/isa.rb
21
25
  lib/tem/ecert.rb
22
26
  lib/tem/hive.rb
23
27
  lib/tem/keys/asymmetric.rb
24
28
  lib/tem/keys/key.rb
25
29
  lib/tem/keys/symmetric.rb
26
- lib/tem/sec_assembler.rb
27
30
  lib/tem/sec_exec_error.rb
28
- lib/tem/sec_opcodes.rb
29
31
  lib/tem/seclosures.rb
30
32
  lib/tem/secpack.rb
31
33
  lib/tem/tem.rb
@@ -42,12 +44,24 @@ LICENSE
42
44
  Manifest
43
45
  Rakefile
44
46
  README
47
+ tem_ruby.gemspec
45
48
  test/_test_cert.rb
46
49
  test/builders/test_abi_builder.rb
47
50
  test/tem_test_case.rb
51
+ test/tem_unit/test_tem_alu.rb
52
+ test/tem_unit/test_tem_bound_secpack.rb
53
+ test/tem_unit/test_tem_branching.rb
54
+ test/tem_unit/test_tem_crypto_asymmetric.rb
55
+ test/tem_unit/test_tem_crypto_hash.rb
56
+ test/tem_unit/test_tem_crypto_pstore.rb
57
+ test/tem_unit/test_tem_crypto_random.rb
58
+ test/tem_unit/test_tem_emit.rb
59
+ test/tem_unit/test_tem_memory.rb
60
+ test/tem_unit/test_tem_memory_compare.rb
61
+ test/tem_unit/test_tem_output.rb
62
+ test/tem_unit/test_tem_yaml_secpack.rb
48
63
  test/test_driver.rb
49
64
  test/test_exceptions.rb
50
- test/test_tem.rb
51
65
  test/transport/test_auto_configurator.rb
52
66
  test/transport/test_java_card_mixin.rb
53
67
  test/transport/test_jcop_remote.rb
@@ -41,8 +41,7 @@ module Buffers
41
41
 
42
42
  chunk_id, offset = 0, 0
43
43
  while offset < data.length do
44
- write_size = (data.length - offset < @buffer_chunk_size) ?
45
- data.length - offset : @buffer_chunk_size
44
+ write_size = [data.length - offset, @buffer_chunk_size].min
46
45
  @transport.applet_apdu! :ins => 0x24, :p1 => buffer_id, :p2 => chunk_id,
47
46
  :data => data[offset, write_size]
48
47
  chunk_id += 1
@@ -4,11 +4,11 @@ require 'openssl'
4
4
  # :nodoc: namespace
5
5
  module Tem::Builders
6
6
 
7
- # Builder class and namespace for the ABI builder.
7
+ # Builder class for the ABI (Abstract Binary Interface) builder.
8
8
  class Abi
9
9
  # Creates a builder targeting a module / class.
10
10
  #
11
- # The given parameter should be a class or module
11
+ # The given parameter should be a class or module.
12
12
  def self.define_abi(class_or_module) # :yields: abi
13
13
  yield new(class_or_module)
14
14
  end
@@ -0,0 +1,314 @@
1
+ # :nodoc: namespace
2
+ module Tem::Builders
3
+
4
+ # Builder class for the code assembler builder.
5
+ class Assembler
6
+ # Creates a builder targeting a module / class.
7
+ #
8
+ # The given parameter should be a class or module.
9
+ def self.define_assembler(class_or_module) # :yields: abi
10
+ yield new(class_or_module)
11
+ end
12
+
13
+ # Defines the ISA targeted by the assembler.
14
+ #
15
+ # This method should be called early in the assembler definition. It creates
16
+ # the proxy and builder classes for the assembling process.
17
+ def target_isa(isa_module)
18
+ @isa = isa_module
19
+ target.const_set :Isa, @isa
20
+ @abi = @isa.const_get :Abi
21
+ target.const_set :Abi, @abi
22
+
23
+ define_proxy_class
24
+ define_builder_class
25
+ augment_target
26
+ end
27
+
28
+ # Defines the methods for implementing a stack directive.
29
+ #
30
+ # The following options are supported:
31
+ # label:: the label serving as the stack marker (required)
32
+ # slot_type:: the ABI type representing a stack slot
33
+ #
34
+ # The following method is defined in the proxy for a directive named 'name':
35
+ # * name(slots = 0) -> places a stack marker and allocates stack slots
36
+ def stack_directive(name, options)
37
+ unless @proxy_class
38
+ raise "target_isa must be called before other builder methods"
39
+ end
40
+ # Capture these in the closure.
41
+ stack_label = options[:label]
42
+ slot_length = @abi.send :"#{options[:slot_type]}_length"
43
+ proxy_defines = Proc.new do
44
+ define_method name.to_sym do |*args|
45
+ case args.length
46
+ when 0
47
+ slots = 0
48
+ when 1
49
+ slots = args.first
50
+ else
51
+ raise "#{name}: given #{args.length} arguments, wanted at most 1"
52
+ end
53
+ @assembler.emit_label stack_label
54
+ if slots > 0
55
+ @assembler.emit_bytes name, :emit => Array.new(slots * slot_length, 0)
56
+ end
57
+ end
58
+ end
59
+ @proxy_class.class_eval &proxy_defines
60
+ (class << @proxy_class; self; end).module_eval &proxy_defines
61
+ end
62
+
63
+ # Defines the methods for implementing a labeling directive.
64
+ #
65
+ # The following method is defined in the proxy for a directive named 'name':
66
+ # * name(label_name) -> creates a label named label_name at the current byte
67
+ def label_directive(name, options = {})
68
+ unless @proxy_class
69
+ raise "target_isa must be called before other builder methods"
70
+ end
71
+ proxy_defines = Proc.new do
72
+ define_method name.to_sym do |label_name|
73
+ @assembler.emit_label label_name.to_sym
74
+ end
75
+ end
76
+ @proxy_class.class_eval &proxy_defines
77
+ (class << @proxy_class; self; end).module_eval &proxy_defines
78
+ end
79
+
80
+ # Defines the methods for implementing a special label directive.
81
+ #
82
+ # The following method is defined in the proxy for a directive named 'name':
83
+ # * name -> creates a label named label_name at the current byte
84
+ def special_label_directive(name, label_name)
85
+ unless @proxy_class
86
+ raise "target_isa must be called before other builder methods"
87
+ end
88
+ proxy_defines = Proc.new do
89
+ define_method name.to_sym do
90
+ @assembler.emit_label label_name.to_sym
91
+ end
92
+ end
93
+ @proxy_class.class_eval &proxy_defines
94
+ (class << @proxy_class; self; end).module_eval &proxy_defines
95
+ end
96
+
97
+ # Defines the methods for implementing a zero-inserting directive.
98
+ #
99
+ # The following method is defined in the proxy for a directive named 'name':
100
+ # * name(abi_type, count = 1) -> creates count zeros of abi_type
101
+ def zeros_directive(name, options = {})
102
+ unless @proxy_class
103
+ raise "target_isa must be called before other builder methods"
104
+ end
105
+ # Capture this in the closure.
106
+ abi = @abi
107
+ proxy_defines = Proc.new do
108
+ define_method name.to_sym do |*args|
109
+ if args.length == 1 || args.length == 2
110
+ type_name, count = args[0], args[1] || 1
111
+ else
112
+ raise "#{name}: given #{args.length} arguments, wanted 1 or 2"
113
+ end
114
+ bytes = count * abi.send(:"#{type_name}_length")
115
+ @assembler.emit_bytes name, :emit => Array.new(bytes, 0)
116
+ end
117
+ end
118
+ @proxy_class.class_eval &proxy_defines
119
+ (class << @proxy_class; self; end).module_eval &proxy_defines
120
+ end
121
+
122
+ # Defines the methods for implementing a data-emitting directive.
123
+ #
124
+ # The following method is defined in the proxy for a directive named 'name':
125
+ # * name(abi_type, values = 1) -> emits the given values as abi_type
126
+ def data_directive(name, options = {})
127
+ unless @proxy_class
128
+ raise "target_isa must be called before other builder methods"
129
+ end
130
+ # Capture this in the closure.
131
+ abi = @abi
132
+ proxy_defines = Proc.new do
133
+ define_method name.to_sym do |abi_type, values|
134
+ values = [values] unless values.instance_of? Array
135
+ data = []
136
+ values.each { |value| data += abi.send :"to_#{abi_type}", value }
137
+ @assembler.emit_bytes :immed, :emit => data
138
+ end
139
+ end
140
+ @proxy_class.class_eval &proxy_defines
141
+ (class << @proxy_class; self; end).module_eval &proxy_defines
142
+ end
143
+
144
+ # (private) Defines the builder class used during assembly.
145
+ #
146
+ # Builders maintain intermediate results during the assembly process. In a
147
+ # nutshell, a builder collects the bytes, labels and linker directives, and
148
+ # puts them together at the end of the assembly process.
149
+ #
150
+ # Builder classes are synthesized automatically if they don't already exist.
151
+ # To have a builder class inherit from another class, define it before calling
152
+ # target_isa. Builder classes are saved as the Builder constant in the
153
+ # assembler class.
154
+ #
155
+ # Builder classes are injected the code in Assembler::CodeBuilderBase. Look
156
+ # there for override hooks into the assembly process.
157
+ def define_builder_class
158
+ if @target.const_defined? :Builder
159
+ @builder_class = @taget.const_get :Builder
160
+ else
161
+ @builder_class = Class.new
162
+ @target.const_set :Builder, @builder_class
163
+ end
164
+ @builder_class.send :include, Assembler::CodeBuilderBase
165
+ end
166
+ private :define_builder_class
167
+
168
+ # (private) Defines the proxy class used during assembly.
169
+ #
170
+ # The proxy class is yielded to the block given to the assemble call, which
171
+ # provides the code to be assembled. For clarity, the proxy class is
172
+ # synthesized so it only contains the methods that are useful for assembly.
173
+ #
174
+ # The proxy class is always automatically synthesized, and is available under
175
+ # the constant Proxy in the assembler class.
176
+ def define_proxy_class
177
+ @proxy_class = Class.new Assembler::ProxyBase
178
+ target.const_set :Proxy, @proxy_class
179
+
180
+ @proxy_class.const_set :Abi, @abi
181
+ @proxy_class.const_set :Isa, @isa
182
+
183
+ # Capture the ISA and ABI in the closure.
184
+ isa = @isa
185
+ proxy_defines = Proc.new do
186
+ isa.instance_methods.each do |method|
187
+ if method[0, 5] == 'emit_'
188
+ isa_method_msg = method.to_sym
189
+ proxy_method_name = method[5, method.length].to_sym
190
+ define_method proxy_method_name do |*args|
191
+ emit_data = isa.send isa_method_msg, *args
192
+ @assembler.emit_bytes proxy_method_name, emit_data
193
+ end
194
+ end
195
+ end
196
+ end
197
+ @proxy_class.class_eval &proxy_defines
198
+ (class << @proxy_class; self; end).module_eval &proxy_defines
199
+ end
200
+ private :define_proxy_class
201
+
202
+ # (private) Augments the target with the assemble method.
203
+ def augment_target
204
+ # Capture this data in the closure.
205
+ proxy_class = @proxy_class
206
+ builder_class = @builder_class
207
+ defines = Proc.new do
208
+ # Assembles code.
209
+ def assemble(&block)
210
+ _assemble block
211
+ end
212
+
213
+ # Internal method for assembling code.
214
+ #
215
+ # We need to use a block to define this method, so we can capture the
216
+ # outer variables (proxy_class and builder_class) in its closure. However,
217
+ # blocks can't take blocks as parameters (at least not in MRI 1.8). So
218
+ # we use a regular method definition (assemble) which wraps the block
219
+ # into a Proc received by _assemble.
220
+ define_method :_assemble do |block|
221
+ code_builder = builder_class.new
222
+ code_builder.start_assembling
223
+ proxy = proxy_class.new(code_builder)
224
+ block.call proxy
225
+ code_builder.done_assembling proxy
226
+ end
227
+ private :_assemble
228
+ end
229
+ @target.class_eval &defines
230
+ (class << @target; self; end).module_eval &defines
231
+ end
232
+
233
+ # The module / class impacted by the builder.
234
+ attr_reader :target
235
+
236
+ # Creates a builder targeting a module / class.
237
+ def initialize(target)
238
+ @target = target
239
+ @isa, @abi, @proxy = nil, nil, nil
240
+ end
241
+ private_class_method :new
242
+ end # class Assembler
243
+
244
+
245
+ # Base class for the assemblers' proxy objects.
246
+ #
247
+ # The proxy object is the object that is yielded out of an assembler's
248
+ # assemble class method.
249
+ class Assembler::ProxyBase
250
+ def initialize(assembler)
251
+ @assembler = assembler
252
+ end
253
+ end
254
+
255
+ # Module injected into the assembler's code builder class.
256
+ module Assembler::CodeBuilderBase
257
+ # Called by assemble before its associated block receives control.
258
+ #
259
+ # This method is responsible for setting up the state needed by the emit_
260
+ # methods.
261
+ def start_assembling
262
+ @bytes = []
263
+ @link_directives = []
264
+ @line_info = []
265
+ @labels = {}
266
+ end
267
+
268
+ # Emits code or data bytes, with associated link directives.
269
+ def emit_bytes(emit_atom_name, emit_data)
270
+ (emit_data[:link_directives] || []).each do |directive|
271
+ directive[:offset] += @bytes.length
272
+ @link_directives << directive
273
+ end
274
+
275
+ emit_data[:emit] ||= []
276
+ if emit_data[:emit].length > 0
277
+ @line_info << [@bytes.length, emit_atom_name, Kernel.caller(2)]
278
+ end
279
+ @bytes += emit_data[:emit] || []
280
+ end
281
+
282
+ # Emits labels, which are symbolic names for addresses.
283
+ def emit_label(label_name)
284
+ raise "label #{label_name} already defined" if @labels[label_name]
285
+ @labels[label_name] = @bytes.length
286
+ end
287
+
288
+ # Called by assemble after its associated block returns.
289
+ #
290
+ # This method is responsible for the final assembly steps (i.e. linking) and
291
+ # returning a processed result. The method's result is returned by assemble.
292
+ def done_assembling(proxy)
293
+ # Process link directives.
294
+ abi = proxy.class.const_get :Abi
295
+ @link_directives.each do |directive|
296
+ if label = directive[:label]
297
+ raise "Label #{label} undefined" unless address = @labels[label]
298
+ else
299
+ address = directive[:address]
300
+ end
301
+ if directive[:relative]
302
+ address -= directive[:offset] + directive[:relative]
303
+ end
304
+ address_bytes = abi.send :"signed_to_#{directive[:type]}", address
305
+ @bytes[directive[:offset], address_bytes.length] = *address_bytes
306
+ end
307
+
308
+ # Wrap all the built data into a nice package and return it.
309
+ { :bytes => @bytes, :link_directives => @link_direcives, :labels => @labels,
310
+ :line_info => @line_info }
311
+ end
312
+ end
313
+
314
+ end # namespace Tem::Builders
@@ -28,18 +28,25 @@ class Crypto < Abi
28
28
  # * public_name_class -> Class
29
29
  def asymmetric_key(name, ssl_class, privkey_abi_type, pubkey_abi_type,
30
30
  hooks = {})
31
- object_wrapper "private_#{name}", ssl_class, [privkey_abi_type, nil],
32
- :read => hooks[:read_private] || hooks[:read],
33
- :to => hooks[:to_private] || hooks[:to],
31
+ object_wrapper "private_#{name}", Tem::Keys::Asymmetric,
32
+ [privkey_abi_type, nil],
33
+ :read => hooks[:read_private] || hooks[:read] ||
34
+ lambda { |k| Tem::Keys::Asymmetric.new k },
35
+ :to => hooks[:to_private] || hooks[:to] ||
36
+ lambda { |k| k.ssl_key },
34
37
  :new => hooks[:new_private] || hooks[:new] ||
35
38
  lambda { |k| ssl_class.new }
36
- object_wrapper "public_#{name}", ssl_class, [pubkey_abi_type, nil],
37
- :read => hooks[:read_public] || hooks[:read],
38
- :to => hooks[:to_public] || hooks[:to],
39
+ object_wrapper "public_#{name}", Tem::Keys::Asymmetric,
40
+ [pubkey_abi_type, nil],
41
+ :read => hooks[:read_public] || hooks[:read] ||
42
+ lambda { |k| Tem::Keys::Asymmetric.new k },
43
+ :to => hooks[:to_public] || hooks[:to] ||
44
+ lambda { |k| k.ssl_key },
39
45
  :new => hooks[:new_private] || hooks[:new] ||
40
46
  lambda { |k| ssl_class.new }
41
47
  end
42
48
 
49
+
43
50
  # Defines the methods for a symmetric key.
44
51
  #
45
52
  # cipher_class should be a class in OpenSSL::Cipher. key_abi_type should be
@@ -50,9 +57,11 @@ class Crypto < Abi
50
57
  # * to_name(object) -> array
51
58
  # * name_class -> Class
52
59
  def symmetric_key(name, cipher_class, cipher_name, key_abi_type, hooks = {})
53
- object_wrapper name, cipher_class, [key_abi_type, :key],
60
+ object_wrapper name, Tem::Keys::Symmetric, [key_abi_type, :key],
61
+ :read => lambda { |k| Tem::Keys::Symmetric.new k },
62
+ :to => lambda { |k| k.ssl_key },
54
63
  :new => lambda { |klass|
55
- k = klass.new cipher_name
64
+ k = cipher_class cipher_name
56
65
 
57
66
  unless k.respond_to? :key
58
67
  # Some ciphers don't give back the key that they receive.
@@ -0,0 +1,120 @@
1
+ require 'openssl'
2
+
3
+
4
+ # :nodoc: namespace
5
+ module Tem::Builders
6
+
7
+ # Builder class for the ISA (Instruction Set Architecture) builder.
8
+ class Isa
9
+ # Creates a builder targeting a module / class.
10
+ #
11
+ # class_or_module will receive the ISA method definitions. abi should be a
12
+ # class or module containing the ABI definitions that the ISA definitions
13
+ # refer to.
14
+ #
15
+ # The following options are supported:
16
+ # opcode_type:: the ABI type encoding the instructions' opcodes (required)
17
+ def self.define_isa(class_or_module, abi, options) # :yields: isa
18
+ yield new(class_or_module, abi, options[:opcode_type])
19
+ end
20
+
21
+ # Defines the methods for handling an instruction in the IA.
22
+ #
23
+ # The instruction's arguments are provided as an array of hashes. Each hash
24
+ # describes one argument, and the ordering in the array reflects the encoding
25
+ # order. The following hash keys are supported:
26
+ # name:: if defined, the argument can be provided as a named argument;
27
+ # named arguments must follow positional arguments
28
+ # type:: the ABI type encoding the argument (required)
29
+ # reladdr:: if defined, the encoded argument value is relative to the
30
+ # address of the instruction containing the argument;
31
+ #
32
+ # The result of encoding an instruction is a Hash with the following keys:
33
+ # emit:: the bytes to be emitted into the code stream
34
+ # link_directives:: an array of directives for the code linker
35
+ #
36
+ # Each linker directive refers to an address cell (location in the code
37
+ # representing an address that the linker must adjust. The following keys can
38
+ # be present:
39
+ # type:: the ABI type for the address cell (required)
40
+ # offset:: the address cell's offset in the emitted bytes (required)
41
+ # address:: the absolute address to point to (mutually exclusive with label)
42
+ # label:: the name of a label that the address must point to
43
+ # relative:: if false, the address cell holds an absolute address;
44
+ # otherwise, the cell's value is computed as follows:
45
+ # target address - cell address + value of relative;
46
+ # (optional, default value is false)
47
+ # The following methods are defined for a type named 'name':
48
+ # * encode_name(*arguments) -> Hash
49
+ def instruction(opcode, name, *iargs)
50
+ encoded_opcode = @abi.send :"to_#{@opcode_type}", opcode
51
+ abi = @abi # Capture the ABI in the method closures.
52
+ named_indexes = {}
53
+ iargs.map { |iarg| iarg[:name] }.
54
+ each_with_index { |argname, i| named_indexes[argname] = i if argname }
55
+ arg_encode_msgs = iargs.map { |iarg| :"to_#{iarg[:type]}" }
56
+ defines = Proc.new do
57
+ define_method :"emit_#{name}" do |*args|
58
+ # Flatten arguments by resolving named parameters to indexes.
59
+ arg_index = 0
60
+ fargs = []
61
+ args.each_with_index do |arg, i|
62
+ fargs[i] = arg and next unless arg.kind_of? Hash
63
+
64
+ if i != args.length - 1
65
+ raise "Named arguments must follow inline arguments! (arg #{i})"
66
+ end
67
+ arg.each do |k, v|
68
+ raise "#{name} has no #{k} argument" unless i = named_indexes[k]
69
+ raise "Argument #{k} was already assigned a value" if fargs[i]
70
+ fargs[i] = v
71
+ end
72
+ end
73
+
74
+ arg_count = fargs.inject(0) { |acc, v| v.nil? ? acc : acc + 1 }
75
+ if arg_count != iargs.length
76
+ raise "#{name} requires #{fargs.length} args, given #{arg_count}"
77
+ end
78
+
79
+ # Encode parameters.
80
+ # @lines[@body.length] = Kernel.caller(0)
81
+
82
+ emit = encoded_opcode
83
+ link_directives = []
84
+ fargs.each_with_index do |arg, i|
85
+ if (arg.kind_of? Numeric) && !arg[:reladdr]
86
+ emit += abi.send arg_encode_msgs[i], arg
87
+ else
88
+ link_directive = { :type => iargs[i][:type], :offset => emit.length,
89
+ :relative => iargs[i][:reladdr] || false }
90
+ if arg.kind_of? Numeric
91
+ link_directive[:address] = arg.to_i
92
+ else
93
+ link_directive[:label] = arg.to_sym
94
+ end
95
+ link_directives << link_directive
96
+ emit += abi.send arg_encode_msgs[i], 0
97
+ end
98
+ end
99
+ { :emit => emit, :link_directives => link_directives }
100
+ end
101
+ end
102
+
103
+ @target.class_eval &defines
104
+ (class << @target; self; end).module_eval &defines
105
+ end
106
+
107
+ # The module / class impacted by the builder.
108
+ attr_reader :target
109
+
110
+ # Creates a builder targeting a module / class.
111
+ def initialize(target, abi, opcode_type)
112
+ @target = target
113
+ @target.const_set :Abi, abi
114
+ @abi = abi
115
+ @opcode_type = opcode_type
116
+ end
117
+ private_class_method :new
118
+ end # class Isa
119
+
120
+ end # namespace Tem::Builders
@@ -24,12 +24,13 @@ module Tem::Abi
24
24
  Tem::Builders::Crypto.define_crypto self do |crypto|
25
25
  crypto.crypto_hash :tem_hash, Digest::SHA1
26
26
 
27
- crypto.asymmetric_key :tem_rsa, Tem::Keys::Asymmetric, :tem_privrsa_numbers,
28
- :tem_pubrsa_numbers, :new => lambda { |key| OpenSSL::PKey::RSA.new },
29
- :to => lambda { |k| k.ssl_key },
30
- :read_public => lambda { |key| Tem::Keys::Asymmetric.new key },
27
+ crypto.asymmetric_key :tem_rsa, OpenSSL::PKey::RSA, :tem_privrsa_numbers,
28
+ :tem_pubrsa_numbers,
31
29
  :read_private => lambda { |key|
32
- # a bit of math to rebuild the public key
30
+ # The TEM uses the Chinese Remainder Theorem form of RSA keys, while
31
+ # OpenSSL uses the straightforward form (n, e, d).
32
+
33
+ # Rebuild the straightforward form from the CRT form.
33
34
  key.n = key.p * key.q
34
35
  p1, q1 = key.p - 1, key.q - 1
35
36
  p1q1 = p1 * q1
@@ -42,11 +43,8 @@ module Tem::Abi
42
43
  Tem::Keys::Asymmetric.new key
43
44
  }
44
45
 
45
- crypto.symmetric_key :tem_aes_key, Tem::Keys::Symmetric, nil,
46
- :tem_aes_key_string,
47
- :new => lambda { |k| OpenSSL::Cipher::AES.new 'ECB' },
48
- :read => lambda { |k| Tem::Keys::Symmetric.new k },
49
- :to => lambda { |k| k.ssl_key }
46
+ crypto.symmetric_key :tem_aes_key, OpenSSL::Cipher::AES, 'ECB',
47
+ :tem_aes_key_string
50
48
 
51
49
  crypto.conditional_wrapper :tem_key, 1,
52
50
  [{:tag => [0x99], :type => :tem_key,
@@ -0,0 +1,23 @@
1
+ class Tem::Assembler
2
+ Tem::Builders::Assembler.define_assembler self do |assembler|
3
+ assembler.target_isa Tem::Isa
4
+ assembler.stack_directive :stack, :label => :__stack,
5
+ :slot_type => :tem_short
6
+ assembler.label_directive :label
7
+ assembler.special_label_directive :entry, :__entry
8
+ assembler.zeros_directive :zeros
9
+ assembler.data_directive :data
10
+ end
11
+
12
+ class Builder
13
+ def done_assembling(proxy)
14
+ assembled = super
15
+ bytes = assembled[:bytes]
16
+ labels = assembled[:labels]
17
+ Tem::SecPack.new :body => bytes,
18
+ :labels => labels, :ep => labels[:__entry] || 0,
19
+ :sp => labels[:__stack] || bytes.length,
20
+ :lines => assembled[:line_info]
21
+ end
22
+ end
23
+ end