costan-tem_ruby 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 (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