tem_ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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