costan-tem_ruby 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/CHANGELOG +45 -0
  2. data/LICENSE +21 -0
  3. data/Manifest +75 -0
  4. data/README +8 -0
  5. data/Rakefile +23 -0
  6. data/bin/tem_bench +9 -0
  7. data/bin/tem_ca +13 -0
  8. data/bin/tem_irb +11 -0
  9. data/bin/tem_proxy +65 -0
  10. data/bin/tem_stat +35 -0
  11. data/dev_ca/ca_cert.cer +0 -0
  12. data/dev_ca/ca_cert.pem +32 -0
  13. data/dev_ca/ca_key.pem +27 -0
  14. data/dev_ca/config.yml +14 -0
  15. data/lib/tem/_cert.rb +158 -0
  16. data/lib/tem/apdus/buffers.rb +89 -0
  17. data/lib/tem/apdus/keys.rb +64 -0
  18. data/lib/tem/apdus/lifecycle.rb +13 -0
  19. data/lib/tem/apdus/tag.rb +38 -0
  20. data/lib/tem/auto_conf.rb +25 -0
  21. data/lib/tem/builders/abi.rb +482 -0
  22. data/lib/tem/builders/assembler.rb +314 -0
  23. data/lib/tem/builders/crypto.rb +124 -0
  24. data/lib/tem/builders/isa.rb +120 -0
  25. data/lib/tem/ca.rb +114 -0
  26. data/lib/tem/definitions/abi.rb +65 -0
  27. data/lib/tem/definitions/assembler.rb +23 -0
  28. data/lib/tem/definitions/isa.rb +188 -0
  29. data/lib/tem/ecert.rb +77 -0
  30. data/lib/tem/hive.rb +18 -0
  31. data/lib/tem/keys/asymmetric.rb +116 -0
  32. data/lib/tem/keys/key.rb +48 -0
  33. data/lib/tem/keys/symmetric.rb +47 -0
  34. data/lib/tem/sec_exec_error.rb +63 -0
  35. data/lib/tem/seclosures.rb +81 -0
  36. data/lib/tem/secpack.rb +107 -0
  37. data/lib/tem/tem.rb +31 -0
  38. data/lib/tem/toolkit.rb +101 -0
  39. data/lib/tem/transport/auto_configurator.rb +87 -0
  40. data/lib/tem/transport/java_card_mixin.rb +99 -0
  41. data/lib/tem/transport/jcop_remote_protocol.rb +59 -0
  42. data/lib/tem/transport/jcop_remote_server.rb +171 -0
  43. data/lib/tem/transport/jcop_remote_transport.rb +65 -0
  44. data/lib/tem/transport/pcsc_transport.rb +87 -0
  45. data/lib/tem/transport/transport.rb +10 -0
  46. data/lib/tem_ruby.rb +47 -0
  47. data/tem_ruby.gemspec +35 -0
  48. data/test/_test_cert.rb +70 -0
  49. data/test/builders/test_abi_builder.rb +298 -0
  50. data/test/tem_test_case.rb +26 -0
  51. data/test/tem_unit/test_tem_alu.rb +33 -0
  52. data/test/tem_unit/test_tem_bound_secpack.rb +51 -0
  53. data/test/tem_unit/test_tem_branching.rb +56 -0
  54. data/test/tem_unit/test_tem_crypto_asymmetric.rb +123 -0
  55. data/test/tem_unit/test_tem_crypto_hash.rb +35 -0
  56. data/test/tem_unit/test_tem_crypto_pstore.rb +53 -0
  57. data/test/tem_unit/test_tem_crypto_random.rb +25 -0
  58. data/test/tem_unit/test_tem_emit.rb +23 -0
  59. data/test/tem_unit/test_tem_memory.rb +48 -0
  60. data/test/tem_unit/test_tem_memory_compare.rb +65 -0
  61. data/test/tem_unit/test_tem_output.rb +32 -0
  62. data/test/tem_unit/test_tem_yaml_secpack.rb +47 -0
  63. data/test/test_driver.rb +108 -0
  64. data/test/test_exceptions.rb +35 -0
  65. data/test/transport/test_auto_configurator.rb +114 -0
  66. data/test/transport/test_java_card_mixin.rb +90 -0
  67. data/test/transport/test_jcop_remote.rb +82 -0
  68. data/timings/blank_bound_secpack.rb +18 -0
  69. data/timings/blank_sec.rb +14 -0
  70. data/timings/devchip_decrypt.rb +9 -0
  71. data/timings/post_buffer.rb +10 -0
  72. data/timings/simple_apdu.rb +5 -0
  73. data/timings/timings.rb +64 -0
  74. data/timings/vm_perf.rb +140 -0
  75. data/timings/vm_perf_bound.rb +141 -0
  76. metadata +201 -0
@@ -0,0 +1,82 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'flexmock/test_unit'
5
+
6
+ require 'tem_ruby'
7
+
8
+ # Tests JcopRemoteProtocol, JcopRemoteServer, and JcopRemoteTransport.
9
+ class JcopRemoteTest < Test::Unit::TestCase
10
+ Protocol = Tem::Transport::JcopRemoteProtocol
11
+ Server = Tem::Transport::JcopRemoteServer
12
+ Transport = Tem::Transport::JcopRemoteTransport
13
+
14
+ # Serving logic that records what it receives and replays a log.
15
+ class Logic
16
+ include Protocol
17
+ attr_reader :received
18
+ def initialize(responses)
19
+ @responses = responses
20
+ @received = []
21
+ end
22
+ def connection_start
23
+ @received << :start
24
+ end
25
+ def connection_end
26
+ @received << :end
27
+ end
28
+ def exchange_apdu(apdu)
29
+ @received << apdu
30
+ @responses.shift
31
+ end
32
+ end
33
+
34
+ def setup
35
+ @server = Server.new(:ip => '127.0.0.1', :port => 51995)
36
+ @client = Transport.new :host => '127.0.0.1', :port => 51995
37
+ @old_abort_on_exception = Thread.abort_on_exception
38
+ Thread.abort_on_exception = true
39
+ end
40
+
41
+ def teardown
42
+ Thread.abort_on_exception = @old_abort_on_exception
43
+ @server.stop
44
+ end
45
+
46
+ def test_apdu_exchange
47
+ apdu_request = [0x31, 0x41, 0x59, 0x26, 0x53]
48
+ apdu_response = [0x27, 0x90, 0x00]
49
+
50
+ logic = Logic.new([apdu_response])
51
+ Thread.new do
52
+ begin
53
+ @server.run logic
54
+ rescue Exception
55
+ print $!, "\n"
56
+ print $!.backtrace.join("\n")
57
+ raise
58
+ end
59
+ end
60
+ Kernel.sleep 0.05 # Wait for the server to start up.
61
+ @client.connect
62
+ assert_equal apdu_response, @client.exchange_apdu(apdu_request)
63
+ @client.disconnect
64
+ Kernel.sleep 0.05 # Wait for the server to process the disconnect.
65
+ assert_equal [:start, apdu_request, :end], logic.received
66
+ end
67
+
68
+ def test_java_card_integration
69
+ apdu_request = [0x00, 0x31, 0x41, 0x59, 0x00]
70
+ apdu_response = [0x27, 0x90, 0x00]
71
+
72
+ logic = Logic.new([apdu_response])
73
+ Thread.new { @server.run logic }
74
+ Kernel.sleep 0.05 # Wait for the server to start up.
75
+ @client.connect
76
+ assert_equal [0x27],
77
+ @client.applet_apdu!(:ins => 0x31, :p1 => 0x41, :p2 => 0x59)
78
+ @client.disconnect
79
+ Kernel.sleep 0.05 # Wait for the server to process the disconnect.
80
+ assert_equal [:start, apdu_request, :end], logic.received
81
+ end
82
+ end
@@ -0,0 +1,18 @@
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.zeros :tem_ubyte, 50
9
+ s.label :plain
10
+ s.zeros :tem_ubyte, 220
11
+ s.stack 1
12
+ }
13
+ secpack.bind @tem.pubek, :secret, :plain
14
+
15
+ print "SECpack has #{secpack.body.length} bytes, runs 3 instructions and produces 0 bytes\n"
16
+ do_timing { @tem.execute secpack }
17
+ end
18
+ end
@@ -0,0 +1,14 @@
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.zeros :tem_ubyte, 70
8
+ s.stack 1
9
+ }
10
+
11
+ print "SECpack has #{secpack.body.length} bytes, runs 3 instructions and produces 0 bytes\n"
12
+ do_timing { @tem.execute secpack }
13
+ end
14
+ 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,64 @@
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
+ @tem = Tem.auto_tem
14
+
15
+ @tem.kill
16
+ @tem.activate
17
+ @tem.emit
18
+ end
19
+
20
+ def teardown
21
+ @tem.kill
22
+ @tem.disconnect if @tem
23
+ end
24
+
25
+ def do_timing
26
+ @tem.flush_buffers
27
+
28
+ n = 10
29
+ loop do
30
+ timings = (0...3).map do |i|
31
+ t_start = Time.now
32
+ n.times do
33
+ yield
34
+ end
35
+ t_delta = Time.now - t_start
36
+ end
37
+ avg_time = timings.inject { |a,v| a + v } / timings.length
38
+ max_diff = timings.map { |t| (t - avg_time).abs }.max
39
+ print "%8d: %3.8fs per run, %3.8fs uncertainty (%2.5f%%)\n" % [n, avg_time / n, max_diff / n, 100 * max_diff / avg_time]
40
+
41
+ return avg_time unless max_diff / avg_time >= 0.01
42
+ n *= 2
43
+ end
44
+ end
45
+
46
+ def self.all_timings
47
+ timings = {}
48
+ t = TemTimings.new
49
+ t.setup
50
+ t.methods.select { |m| m =~ /time_/ }.each do |m|
51
+ print "Timing: #{m[5..-1]}...\n"
52
+ timings[m] = t.send m.to_sym
53
+ end
54
+ t.teardown
55
+ timings
56
+ end
57
+ end
58
+
59
+ if __FILE__ == $0
60
+ timings = TemTimings.all_timings
61
+ timings.map { |k, v| [k.to_s, v] }.sort.each do |timing|
62
+ print "#{timing.first}: #{'%.5f' % timing.last}s\n"
63
+ end
64
+ end
@@ -0,0 +1,140 @@
1
+ class TemTimings
2
+ def time_vm_perf
3
+ secpack = @tem.assemble { |s|
4
+ s.ldwc 48 * 10
5
+ s.outnew
6
+
7
+ s.ldwc 10 # number of times to loop (4 instructions in loop)
8
+ s.label :main_loop
9
+
10
+ # arithmetic (18 instructions, 10 bytes out)
11
+ s.ldwc 0x1234
12
+ s.ldwc 0x5678
13
+ s.dupn :n => 2
14
+ s.add
15
+ s.outw
16
+ s.sub
17
+ s.outw
18
+ s.ldwc 0x0155
19
+ s.ldwc 0x02AA
20
+ s.mul
21
+ s.outw
22
+ s.ldwc 0x390C
23
+ s.ldwc 0x00AA
24
+ s.dupn :n => 2
25
+ s.div
26
+ s.outw
27
+ s.mod
28
+ s.outw
29
+
30
+ # memory (28 instructions, 16 bytes out)
31
+ s.ldwc 0x55AA
32
+ s.stw :clobber
33
+ s.ldb :clobber
34
+ s.outw
35
+ s.ldw :clobber
36
+ s.outw
37
+ s.ldbc 0xA5 - (1 << 8)
38
+ s.stb :clobber
39
+ s.ldw :clobber
40
+ s.outw
41
+ s.ldwc :clobber2
42
+ s.dupn :n => 1
43
+ s.dupn :n => 2
44
+ s.ldwc 0x9966 - (1 << 16)
45
+ s.stwv
46
+ s.ldbv
47
+ s.outw
48
+ s.ldbc 0x98 - (1 << 8)
49
+ s.stbv
50
+ s.ldwv
51
+ s.outw
52
+ s.ldwc 0x1122
53
+ s.ldwc 0x3344
54
+ s.ldwc 0x5566
55
+ s.flipn :n => 3
56
+ s.outw
57
+ s.outw
58
+ s.outw
59
+
60
+ # memory comparisons (22 instructions, 16 bytes out)
61
+ s.ldwc :const => 6
62
+ s.ldwc :cmp_med
63
+ s.ldwc :cmp_lo
64
+ s.mcmpvb
65
+ s.outw
66
+ s.mcmpfxb :size => 6, :op1 => :cmp_med, :op2 => :cmp_hi
67
+ s.outw
68
+ s.ldwc :const => 4
69
+ s.ldwc :cmp_lo
70
+ s.ldwc :cmp_med
71
+ s.mcmpvb
72
+ s.outw
73
+ s.mcfxb :size => 6, :from => :cmp_hi, :to => :copy_buf
74
+ s.pop
75
+ s.outfxb :size => 6, :from => :copy_buf
76
+ s.ldwc :const => 4
77
+ s.ldwc :cmp_hi
78
+ s.ldwc :copy_buf2
79
+ s.mcvb
80
+ s.pop
81
+ s.outfxb :size => 4, :from => :copy_buf2
82
+
83
+ # jumps (30 instructions, 6 bytes) from 6 * (5 instructions, 1 byte)
84
+ failed = 0xFA - (1 << 8)
85
+ [
86
+ [:ja, [1, 1, failed]],
87
+ [:jae, [1, 4, failed]],
88
+ [:jb, [1, failed, 7]],
89
+ [:jbe, [1, failed, 10]],
90
+ [:jz, [1, failed, 13]],
91
+ [:jne, [1, 16, failed]],
92
+ ].each do |op_line|
93
+ op = op_line.shift
94
+ op_line.each_index do |i|
95
+ then_label = "#{op}_l#{i}_t".to_sym
96
+ out_label = "#{op}_l#{i}_o".to_sym
97
+
98
+ s.ldbc op_line[i][0]
99
+ s.send op, :to => then_label
100
+ s.ldbc op_line[i][2]
101
+ s.jmp :to => out_label
102
+ s.label then_label
103
+ s.ldbc op_line[i][1]
104
+ s.label out_label
105
+ s.outb
106
+ end
107
+ end
108
+
109
+ # loop back
110
+ s.ldbc 1
111
+ s.sub
112
+ s.dupn :n => 1
113
+ s.ja :to => :main_loop
114
+
115
+ s.label :done
116
+ s.halt
117
+
118
+ s.label :cmp_lo
119
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2C, 0x12]
120
+ s.label :cmp_med
121
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2D, 0x11]
122
+ s.label :cmp_hi
123
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
124
+ s.label :cmp_hi2
125
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
126
+ s.label :copy_buf
127
+ s.zeros :tem_ubyte, 6
128
+ s.label :copy_buf2
129
+ s.zeros :tem_ubyte, 4
130
+ s.label :clobber
131
+ s.zeros :tem_ubyte, 2
132
+ s.label :clobber2
133
+ s.zeros :tem_ubyte, 2
134
+ s.label :stack
135
+ s.stack 12
136
+ }
137
+ print "SECpack has #{secpack.body.length} bytes, runs 1020 instructions and produces 470 bytes\n"
138
+ do_timing { @tem.execute secpack }
139
+ end
140
+ end
@@ -0,0 +1,141 @@
1
+ class TemTimings
2
+ def time_vm_perf_bound
3
+ secpack = @tem.assemble { |s|
4
+ s.ldwc 48 * 10
5
+ s.outnew
6
+
7
+ s.ldwc 10 # number of times to loop (4 instructions in loop)
8
+ s.label :main_loop
9
+
10
+ # arithmetic (18 instructions, 10 bytes out)
11
+ s.ldwc 0x1234
12
+ s.ldwc 0x5678
13
+ s.dupn :n => 2
14
+ s.add
15
+ s.outw
16
+ s.sub
17
+ s.outw
18
+ s.ldwc 0x0155
19
+ s.ldwc 0x02AA
20
+ s.mul
21
+ s.outw
22
+ s.ldwc 0x390C
23
+ s.ldwc 0x00AA
24
+ s.dupn :n => 2
25
+ s.div
26
+ s.outw
27
+ s.mod
28
+ s.outw
29
+
30
+ # memory (28 instructions, 16 bytes out)
31
+ s.ldwc 0x55AA
32
+ s.stw :clobber
33
+ s.ldb :clobber
34
+ s.outw
35
+ s.ldw :clobber
36
+ s.outw
37
+ s.ldbc 0xA5 - (1 << 8)
38
+ s.stb :clobber
39
+ s.ldw :clobber
40
+ s.outw
41
+ s.ldwc :clobber2
42
+ s.dupn :n => 1
43
+ s.dupn :n => 2
44
+ s.ldwc 0x9966 - (1 << 16)
45
+ s.stwv
46
+ s.ldbv
47
+ s.outw
48
+ s.ldbc 0x98 - (1 << 8)
49
+ s.stbv
50
+ s.ldwv
51
+ s.outw
52
+ s.ldwc 0x1122
53
+ s.ldwc 0x3344
54
+ s.ldwc 0x5566
55
+ s.flipn :n => 3
56
+ s.outw
57
+ s.outw
58
+ s.outw
59
+
60
+ # memory comparisons (22 instructions, 16 bytes out)
61
+ s.ldwc :const => 6
62
+ s.ldwc :cmp_med
63
+ s.ldwc :cmp_lo
64
+ s.mcmpvb
65
+ s.outw
66
+ s.mcmpfxb :size => 6, :op1 => :cmp_med, :op2 => :cmp_hi
67
+ s.outw
68
+ s.ldwc :const => 4
69
+ s.ldwc :cmp_lo
70
+ s.ldwc :cmp_med
71
+ s.mcmpvb
72
+ s.outw
73
+ s.mcfxb :size => 6, :from => :cmp_hi, :to => :copy_buf
74
+ s.pop
75
+ s.outfxb :size => 6, :from => :copy_buf
76
+ s.ldwc :const => 4
77
+ s.ldwc :cmp_hi
78
+ s.ldwc :copy_buf2
79
+ s.mcvb
80
+ s.pop
81
+ s.outfxb :size => 4, :from => :copy_buf2
82
+
83
+ # jumps (30 instructions, 6 bytes) from 6 * (5 instructions, 1 byte)
84
+ failed = 0xFA - (1 << 8)
85
+ [
86
+ [:ja, [1, 1, failed]],
87
+ [:jae, [1, 4, failed]],
88
+ [:jb, [1, failed, 7]],
89
+ [:jbe, [1, failed, 10]],
90
+ [:jz, [1, failed, 13]],
91
+ [:jne, [1, 16, failed]],
92
+ ].each do |op_line|
93
+ op = op_line.shift
94
+ op_line.each_index do |i|
95
+ then_label = "#{op}_l#{i}_t".to_sym
96
+ out_label = "#{op}_l#{i}_o".to_sym
97
+
98
+ s.ldbc op_line[i][0]
99
+ s.send op, :to => then_label
100
+ s.ldbc op_line[i][2]
101
+ s.jmp :to => out_label
102
+ s.label then_label
103
+ s.ldbc op_line[i][1]
104
+ s.label out_label
105
+ s.outb
106
+ end
107
+ end
108
+
109
+ # loop back
110
+ s.ldbc 1
111
+ s.sub
112
+ s.dupn :n => 1
113
+ s.ja :to => :main_loop
114
+
115
+ s.label :done
116
+ s.halt
117
+
118
+ s.label :cmp_lo
119
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2C, 0x12]
120
+ s.label :cmp_med
121
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2D, 0x11]
122
+ s.label :cmp_hi
123
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
124
+ s.label :cmp_hi2
125
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
126
+ s.label :copy_buf
127
+ s.zeros :tem_ubyte, 6
128
+ s.label :copy_buf2
129
+ s.zeros :tem_ubyte, 4
130
+ s.label :clobber
131
+ s.zeros :tem_ubyte, 2
132
+ s.label :clobber2
133
+ s.zeros :tem_ubyte, 2
134
+ s.label :stack
135
+ s.stack 12
136
+ }
137
+ secpack.bind @tem.pubek, :done, :stack
138
+ print "SECpack has #{secpack.body.length} bytes, runs 1020 instructions and produces 470 bytes\n"
139
+ do_timing { @tem.execute secpack }
140
+ end
141
+ end