tem_ruby 0.9.0

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