tem_ruby 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/test/test_tem.rb DELETED
@@ -1,524 +0,0 @@
1
- require 'test/tem_test_case'
2
-
3
- class TemTest < TemTestCase
4
- def test_alu
5
- sec = @tem.assemble { |s|
6
- s.ldbc 10
7
- s.outnew
8
- s.ldwc 0x1234
9
- s.ldwc 0x5678
10
- s.dupn :n => 2
11
- s.add
12
- s.outw
13
- s.sub
14
- s.outw
15
- s.ldwc 0x0155
16
- s.ldwc 0x02AA
17
- s.mul
18
- s.outw
19
- s.ldwc 0x390C
20
- s.ldwc 0x00AA
21
- s.dupn :n => 2
22
- s.div
23
- s.outw
24
- s.mod
25
- s.outw
26
- s.halt
27
- s.extra 10
28
- }
29
- result = @tem.execute sec
30
- assert_equal [0x68, 0xAC, 0xBB, 0xBC, 0x8C, 0x72, 0x00, 0x55, 0x00, 0x9A],
31
- result, 'the ALU isn\'t working well'
32
- end
33
-
34
- def test_memory
35
- sec = @tem.assemble { |s|
36
- s.label :clobber
37
- s.ldbc 32
38
- s.label :clobber2
39
- s.outnew
40
- s.ldwc 0x55AA
41
- s.stw :clobber
42
- s.ldb :clobber
43
- s.outw
44
- s.ldw :clobber
45
- s.outw
46
- s.ldbc 0xA5 - (1 << 8)
47
- s.stb :clobber
48
- s.ldw :clobber
49
- s.outw
50
- s.ldwc :clobber2
51
- s.dupn :n => 1
52
- s.dupn :n => 2
53
- s.ldwc 0x9966 - (1 << 16)
54
- s.stwv
55
- s.ldbv
56
- s.outw
57
- s.ldbc 0x98 - (1 << 8)
58
- s.stbv
59
- s.ldwv
60
- s.outw
61
- s.ldwc 0x1122
62
- s.ldwc 0x3344
63
- s.ldwc 0x5566
64
- s.flipn :n => 3
65
- s.outw
66
- s.outw
67
- s.outw
68
- s.halt
69
- s.stack
70
- s.extra 10
71
- }
72
- result = @tem.execute sec
73
- assert_equal [0x00, 0x55, 0x55, 0xAA, 0xA5, 0xAA, 0xFF, 0x99, 0x98, 0x66, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66],
74
- result, 'the memory unit isn\'t working well'
75
- end
76
-
77
- def test_output
78
- sec = @tem.assemble { |s|
79
- s.ldbc 32
80
- s.outnew
81
- s.outfxb :size => 3, :from => :area1
82
- s.ldbc 5
83
- s.outvlb :from => :area2
84
- s.ldbc 4
85
- s.ldwc :area3
86
- s.outvb
87
- s.ldwc 0x99AA - (1 << 16)
88
- s.ldwc 0xFA55 - (1 << 16)
89
- s.outb
90
- s.outw
91
- s.halt
92
- s.label :area1
93
- s.immed :ubyte, [0xFE, 0xCD, 0x9A]
94
- s.label :area2
95
- s.immed :ubyte, [0xAB, 0x95, 0xCE, 0xFD, 0x81]
96
- s.label :area3
97
- s.immed :ubyte, [0xEC, 0xDE, 0xAD, 0xCF]
98
- s.stack
99
- s.extra 10
100
- }
101
- result = @tem.execute sec
102
- assert_equal [0xFE, 0xCD, 0x9A, 0xAB, 0x95, 0xCE, 0xFD, 0x81, 0xEC, 0xDE, 0xAD, 0xCF, 0x55, 0x99, 0xAA],
103
- result, 'the output unit isn\'t working well'
104
- end
105
-
106
- def test_branching
107
- secpack = @tem.assemble { |s|
108
- s.ldbc 24
109
- s.outnew
110
-
111
- s.jmp :to => :over_halt
112
- s.halt # this gets jumped over
113
- s.label :over_halt
114
- s.ldbc 4
115
- s.label :test_loop
116
- s.dupn :n => 1
117
- s.outb
118
- s.ldbc 1
119
- s.sub
120
- s.dupn :n=> 1
121
- s.jae :to => :test_loop
122
-
123
- failed = 0xFA - (1 << 8)
124
- [
125
- [:ja, [1, 1, failed], [0, failed, 2], [-1, failed, 3]],
126
- [:jae, [1, 4, failed], [0, 5, failed], [-1, failed, 6]],
127
- [:jb, [1, failed, 7], [0, failed, 8], [-1, 9, failed]],
128
- [:jbe, [1, failed, 10], [0, 11, failed], [-1, 12, failed]],
129
- [:jz, [1, failed, 13], [0, 14, failed], [-1, failed, 15]],
130
- [:jne, [1, 16, failed], [0, failed, 17], [-1, 18, failed]],
131
- ].each do |op_line|
132
- op = op_line.shift
133
- op_line.each_index do |i|
134
- then_label = "#{op}_l#{i}_t".to_sym
135
- out_label = "#{op}_l#{i}_o".to_sym
136
-
137
- s.ldbc op_line[i][0]
138
- s.send op, :to => then_label
139
- s.ldbc op_line[i][2]
140
- s.jmp :to => out_label
141
- s.label then_label
142
- s.ldbc op_line[i][1]
143
- s.label out_label
144
- s.outb
145
- end
146
- end
147
-
148
- s.halt
149
- s.extra 10
150
- }
151
- result = @tem.execute secpack
152
- assert_equal [0x04, 0x03, 0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04,
153
- 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12],
154
- result, 'the branching unit isn\'t working well'
155
- end
156
-
157
- def test_memory_copy_compare(yaml_roundtrip = false)
158
- sec = @tem.assemble { |s|
159
- s.ldwc :const => 16
160
- s.outnew
161
- s.ldwc :const => 6
162
- s.ldwc :cmp_med
163
- s.ldwc :cmp_lo
164
- s.mcmpvb
165
- s.outw
166
- s.mcmpfxb :size => 6, :op1 => :cmp_med, :op2 => :cmp_hi
167
- s.outw
168
- s.ldwc :const => 4
169
- s.ldwc :cmp_lo
170
- s.ldwc :cmp_med
171
- s.mcmpvb
172
- s.outw
173
-
174
- s.mcfxb :size => 6, :from => :cmp_hi, :to => :copy_buf
175
- s.pop
176
- s.outfxb :size => 6, :from => :copy_buf
177
- s.ldwc :const => 4
178
- s.ldwc :cmp_hi
179
- s.ldwc :copy_buf2
180
- s.mcvb
181
- s.pop
182
- s.outfxb :size => 4, :from => :copy_buf2
183
-
184
- s.halt
185
- s.label :cmp_lo
186
- s.immed :ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2C, 0x12]
187
- s.label :cmp_med
188
- s.immed :ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2D, 0x11]
189
- s.label :cmp_hi
190
- s.immed :ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
191
- s.label :cmp_hi2
192
- s.immed :ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
193
- s.label :copy_buf
194
- s.filler :ubyte, 6
195
- s.label :copy_buf2
196
- s.filler :ubyte, 4
197
- s.stack
198
- s.extra 10
199
- }
200
-
201
- if yaml_roundtrip
202
- # same test, except the SECpack is serialized/deserialized
203
- yaml_sec = sec.to_yaml_str
204
- sec = Tem::SecPack.new_from_yaml_str(yaml_sec)
205
- end
206
- result = @tem.execute sec
207
- assert_equal [0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10, 0xA3, 0x2C, 0x51, 0x63],
208
- result, 'memory copy/compare isn\'t working well'
209
- end
210
-
211
- def test_crypto_hash
212
- garbage1 = (0...8).map { |x| (31 * x * x + 5 * x + 3) % 256 }
213
- garbage2 = (0...11).map { |x| (69 * x * x + 62 * x + 10) % 256 }
214
- hash_size = 20
215
-
216
- sec = @tem.assemble { |s|
217
- s.ldwc hash_size * 3
218
- s.outnew
219
- s.mdfxb :size => garbage1.length, :from => :garbage1, :to => :hash_area
220
- s.outfxb :size => hash_size, :from => :hash_area
221
- s.mdfxb :size => garbage2.length, :from => :garbage2, :to => 0xFFFF
222
- s.ldwc garbage2.length
223
- s.ldwc :garbage2
224
- s.ldwc :hash_area
225
- s.mdvb
226
- s.outfxb :size => hash_size, :from => :hash_area
227
- s.halt
228
- s.label :garbage1
229
- s.immed :ubyte, garbage1
230
- s.label :garbage2
231
- s.immed :ubyte, garbage2
232
- s.label :hash_area
233
- s.filler :ubyte, hash_size
234
- s.stack
235
- s.extra 10
236
- }
237
-
238
- result = @tem.execute sec
239
- assert_equal [garbage1, garbage2, garbage2].map { |d| @tem.tem_hash d}.
240
- flatten,
241
- result, 'cryptographic hashing isn\'t working well'
242
- end
243
-
244
- def test_crypto_pstore
245
- addr1 = (0...(@tem.tem_ps_addr_length)).map { |x| (61 * x * x + 62 * x + 10) % 256 }
246
- addr2 = addr1.dup; addr2[addr2.length - 1] += 1
247
- random_value = (0...(@tem.tem_ps_value_length)).map { |x| (69 * x * x + 62 * x + 10) % 256 }
248
-
249
- sec = @tem.assemble { |s|
250
- s.ldwc 3 * @tem.tem_ushort_length + @tem.tem_ps_value_length * 2
251
- s.outnew
252
-
253
- # check that the location is blank
254
- s.ldwc :pstore_addr
255
- s.pshkvb
256
- s.outw
257
-
258
- # write to create the location
259
- s.pswrfxb :addr => :pstore_addr, :from => :s_value
260
- # check that the location isn't blank anymore
261
- s.pshkfxb :addr => :pstore_addr
262
- s.outw
263
- # re-read (should get what was written)
264
- s.ldwc :pstore_addr
265
- s.ldwc :s_value2
266
- s.psrdvb
267
- s.ldwc :s_value2
268
- s.outvb
269
-
270
- # drop the location
271
- s.ldwc :pstore_addr
272
- s.dupn :n => 1
273
- s.psrm
274
- # check that the location is blank again
275
- s.pshkvb
276
- s.outw
277
-
278
- s.halt
279
-
280
- s.label :pstore_addr
281
- s.immed :ubyte, addr1
282
- s.label :s_value
283
- s.immed :ubyte, random_value
284
- s.label :s_value2
285
- s.filler :ps_value
286
- s.stack
287
- s.extra 16
288
- }
289
- expected = @tem.to_tem_ushort(0) + @tem.to_tem_ushort(1) + random_value + @tem.to_tem_ushort(0)
290
- result = @tem.execute sec
291
- assert_equal expected, result, 'persistent store locations aren\'t working well'
292
- end
293
-
294
- def test_crypto_random
295
- sec = @tem.assemble { |s|
296
- s.ldbc 16
297
- s.outnew
298
- s.ldbc 8
299
- s.dupn :n => 1
300
- s.ldwc :rnd_area
301
- s.dupn :n => 2
302
- s.rnd
303
- s.outvb
304
- s.ldbc(-1)
305
- s.rnd
306
- s.halt
307
- s.label :rnd_area
308
- s.filler :ubyte, 8
309
- s.stack
310
- s.extra 10
311
- }
312
-
313
- result = @tem.execute sec
314
- assert_equal 16, result.length, 'monotonic counters aren\'t working well'
315
- end
316
-
317
- def i_crypt(data, key_id, authz, mode = :encrypt, direct_io = true, max_output = nil)
318
- if max_output.nil?
319
- max_output = case mode
320
- when :encrypt
321
- ((data.length + 239) / 240) * 256
322
- when :decrypt
323
- data.length
324
- when :sign
325
- 256
326
- end
327
- end
328
-
329
- crypt_opcode = {:encrypt => :kefxb, :decrypt => :kdfxb, :sign => :ksfxb}[mode]
330
- ex_sec = @tem.assemble { |s|
331
- # buffer
332
- s.ldwc :const => max_output
333
- s.outnew
334
- s.ldbc :const => key_id
335
- s.authk :auth => :key_auth
336
- s.send crypt_opcode, :from => :data, :size => data.length, :to => (direct_io ? 0xFFFF : :outdata)
337
- s.outvlb :from => :outdata unless direct_io
338
- s.halt
339
-
340
- s.label :key_auth
341
- s.immed :ubyte, authz
342
- s.label :data
343
- s.immed :ubyte, data
344
- unless direct_io
345
- s.label :outdata
346
- s.filler :ubyte, max_output
347
- end
348
- s.stack
349
- s.extra 10
350
- }
351
- return @tem.execute(ex_sec)
352
- end
353
-
354
- def i_verify(data, signature, key_id, authz)
355
- sign_sec = @tem.assemble { |s|
356
- # buffer
357
- s.ldbc :const => 1
358
- s.outnew
359
- s.ldbc :const => key_id
360
- s.authk :auth => :key_auth
361
- s.kvsfxb :from => :data, :size => data.length, :signature => :signature
362
- s.outb
363
- s.halt
364
-
365
- s.label :key_auth
366
- s.immed :ubyte, authz
367
- s.label :data
368
- s.immed :ubyte, data
369
- s.label :signature
370
- s.immed :ubyte, signature
371
- s.stack
372
- s.extra 10
373
- }
374
- return @tem.execute(sign_sec)[0] == 1
375
- end
376
-
377
- def i_test_crypto_pki_ops(pubk_id, privk_id, pubk, privk, authz)
378
- garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
379
-
380
- # SEC/priv-sign + CPU/pub-verify, direct IO
381
- signed_garbage = i_crypt(garbage, privk_id, authz, :sign, true)
382
- assert privk.verify(garbage, signed_garbage), 'SEC priv-signing + CPU pub-verify failed on good data'
383
-
384
- # SEC/priv-sign + CPU/pub-verify, indirect IO
385
- signed_garbage = i_crypt(garbage, privk_id, authz, :sign, false)
386
- assert privk.verify(garbage, signed_garbage), 'SEC priv-signing + CPU pub-verify failed on good data'
387
-
388
- # CPU/priv-sign + SEC/pub-verify
389
- signed_garbage = privk.sign garbage
390
- assert i_verify(garbage, signed_garbage, pubk_id, authz), 'CPU priv-signing + SEC pub-verify failed on good data'
391
-
392
- # CPU/priv-encrypt + SEC/pub-decrypt, indirect IO
393
- encrypted_garbage = privk.encrypt garbage
394
- decrypted_garbage = i_crypt(encrypted_garbage, pubk_id, authz, :decrypt, false)
395
- assert_equal garbage, decrypted_garbage, 'SEC priv-encryption + CPU pub-decryption messed up the data'
396
-
397
- # SEC/pub-encrypt + CPU/priv-decrypt, indirect IO
398
- encrypted_garbage = i_crypt(garbage, pubk_id, authz, :encrypt, false)
399
- decrypted_garbage = privk.decrypt encrypted_garbage
400
- assert_equal garbage, decrypted_garbage, 'SEC priv-encryption + CPU pub-decryption messed up the data'
401
-
402
- # CPU/pub-encrypt + SEC/priv-decrypt, direct-IO
403
- encrypted_garbage = pubk.encrypt garbage
404
- decrypted_garbage = i_crypt(encrypted_garbage, privk_id, authz, :decrypt, true)
405
- assert_equal garbage, decrypted_garbage, 'CPU pub-encryption + SEC priv-decryption messed up the data'
406
-
407
- # SEC/priv-encrypt + CPU/pub-decrypt, direct-IO
408
- encrypted_garbage = i_crypt(garbage, privk_id, authz, :encrypt, true)
409
- decrypted_garbage = pubk.decrypt encrypted_garbage
410
- assert_equal garbage, decrypted_garbage, 'SEC priv-encryption + CPU pub-decryption messed up the data'
411
- end
412
-
413
- def test_crypto_pki
414
- # crypto run with an internally generated key
415
- keyd = @tem.tk_gen_key :asymmetric
416
- pubk = @tem.tk_read_key keyd[:pubk_id], keyd[:authz]
417
- privk = @tem.tk_read_key keyd[:privk_id], keyd[:authz]
418
- i_test_crypto_pki_ops(keyd[:pubk_id], keyd[:privk_id], pubk, privk, keyd[:authz])
419
-
420
- # crypto run with an externally generated key
421
- ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
422
- pubk = Tem::Key.new_from_ssl_key ekey.public_key
423
- privk = Tem::Key.new_from_ssl_key ekey
424
- pubk_id = @tem.tk_post_key pubk, keyd[:authz]
425
- privk_id = @tem.tk_post_key privk, keyd[:authz]
426
- i_test_crypto_pki_ops(pubk_id, privk_id, pubk, privk, keyd[:authz])
427
- end
428
-
429
- def test_bound_secpack(yaml_roundtrip = false)
430
- keyd = @tem.tk_gen_key
431
- pubk = @tem.tk_read_key keyd[:pubk_id], keyd[:authz]
432
-
433
- secret = (0...16).map { |i| (99 * i * i + 51 * i + 33) % 256 }
434
- bound_sec = @tem.assemble { |s|
435
- s.ldbc secret.length
436
- s.outnew
437
- s.label :mess_place
438
- s.outfxb :size => secret.length, :from => :secret
439
- s.halt
440
- s.label :secret
441
- s.immed :ubyte, secret
442
- s.label :plain
443
- s.stack
444
- s.extra 8
445
- }
446
-
447
- sb = bound_sec.body
448
- secret_found = false
449
- 0.upto(sb.length - 1) { |i| if secret == sb[i, secret.length] then secret_found = true; break; end }
450
- assert secret_found, 'test_bound_secpack needs rethinking: the unbound secpack does not contain the secret'
451
-
452
- bound_sec.bind pubk, :secret, :plain
453
- if yaml_roundtrip
454
- # same test, except the SECpack is serialized/deserialized
455
- yaml_bound_sec = bound_sec.to_yaml_str
456
- bound_sec = Tem::SecPack.new_from_yaml_str(yaml_bound_sec)
457
- end
458
- result = @tem.execute bound_sec, keyd[:privk_id]
459
- assert_equal secret, result, 'TEM failed to decrypt secpack'
460
-
461
- sb = bound_sec.body
462
- 0.upto(sb.length - 1) { |i| assert_not_equal secret, sb[i, secret.length], 'secret found unencrypted in bound secpack' }
463
-
464
- bound_sec.body[bound_sec.label_address(:mess_place)] += 1
465
- assert_raise(RuntimeError, 'secpack validation isn\'t working') { @tem.execute bound_sec }
466
- end
467
-
468
- def test_yaml_secpack
469
- # simple test to ensure that the body is preserved
470
- sec = @tem.assemble { |s|
471
- s.ldbc 10
472
- s.outnew
473
- s.ldwc 0x1234
474
- s.ldwc 0x5678
475
- s.dupn :n => 2
476
- s.add
477
- s.outw
478
- s.sub
479
- s.outw
480
- s.ldwc 0x0155
481
- s.ldwc 0x02AA
482
- s.mul
483
- s.outw
484
- s.ldwc 0x390C
485
- s.ldwc 0x00AA
486
- s.dupn :n => 2
487
- s.div
488
- s.outw
489
- s.mod
490
- s.outw
491
- s.halt
492
- s.stack
493
- s.extra 10
494
- }
495
- yaml_sec = sec.to_yaml_str
496
- sec2 = Tem::SecPack.new_from_yaml_str(yaml_sec)
497
- assert_equal sec.body, sec2.body, 'SECpack body corrupted during serialization'
498
-
499
- # re-run the memory test (reasonably large SECpack) to ensure that de-serialized SECpacks are equivalent to the originals
500
- test_memory_copy_compare(true)
501
- # re-run the memory test (reasonably large SECpack) to ensure that serialization works on bound SECpacks
502
- test_bound_secpack(true)
503
- end
504
-
505
- def test_emit
506
- # try to emit
507
- er = @tem.emit
508
- assert er != nil, 'TEM emitting failed'
509
-
510
- # now verify that the private key is good and the authorization matches
511
- privek = @tem.tk_read_key 0, er[:privek_auth]
512
- assert((not privek.is_public?), 'TEM emission failed to produce a proper PrivEK')
513
-
514
- # verify that the public key can be read from the ECert
515
- pubek = @tem.pubek
516
- assert pubek.is_public?, 'TEM emission failed to produce a proper PubEK'
517
-
518
- # verify the PrivEK against the ECert
519
- ecert = @tem.endorsement_cert
520
- ecert.verify privek.ssl_key
521
-
522
- @tem.tk_delete_key 0, er[:privek_auth]
523
- end
524
- end