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,65 @@
1
+ require 'test/tem_test_case'
2
+
3
+ module TemMemoryCompareTestCase
4
+ # This is also called from TemYamlSecpackTest.
5
+ def _test_memory_copy_compare(yaml_roundtrip = false)
6
+ sec = @tem.assemble { |s|
7
+ s.ldwc :const => 16
8
+ s.outnew
9
+ s.ldwc :const => 6
10
+ s.ldwc :cmp_med
11
+ s.ldwc :cmp_lo
12
+ s.mcmpvb
13
+ s.outw
14
+ s.mcmpfxb :size => 6, :op1 => :cmp_med, :op2 => :cmp_hi
15
+ s.outw
16
+ s.ldwc :const => 4
17
+ s.ldwc :cmp_lo
18
+ s.ldwc :cmp_med
19
+ s.mcmpvb
20
+ s.outw
21
+
22
+ s.mcfxb :size => 6, :from => :cmp_hi, :to => :copy_buf
23
+ s.pop
24
+ s.outfxb :size => 6, :from => :copy_buf
25
+ s.ldwc :const => 4
26
+ s.ldwc :cmp_hi
27
+ s.ldwc :copy_buf2
28
+ s.mcvb
29
+ s.pop
30
+ s.outfxb :size => 4, :from => :copy_buf2
31
+
32
+ s.halt
33
+ s.label :cmp_lo
34
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2C, 0x12]
35
+ s.label :cmp_med
36
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2D, 0x11]
37
+ s.label :cmp_hi
38
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
39
+ s.label :cmp_hi2
40
+ s.data :tem_ubyte, [0xA3, 0x2C, 0x51, 0x63, 0x2E, 0x10]
41
+ s.label :copy_buf
42
+ s.zeros :tem_ubyte, 6
43
+ s.label :copy_buf2
44
+ s.zeros :tem_ubyte, 4
45
+ s.stack 5
46
+ }
47
+
48
+ if yaml_roundtrip
49
+ # same test, except the SECpack is serialized/deserialized
50
+ yaml_sec = sec.to_yaml_str
51
+ sec = Tem::SecPack.new_from_yaml_str(yaml_sec)
52
+ end
53
+ result = @tem.execute sec
54
+ assert_equal [0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xA3, 0x2C, 0x51, 0x63,
55
+ 0x2E, 0x10, 0xA3, 0x2C, 0x51, 0x63],
56
+ result, 'memory copy/compare isn\'t working well'
57
+ end
58
+ end
59
+
60
+ class TemMemoryCompareTest < TemTestCase
61
+ include TemMemoryCompareTestCase
62
+ def test_memory_copy_compare
63
+ _test_memory_copy_compare false
64
+ end
65
+ end
@@ -0,0 +1,32 @@
1
+ require 'test/tem_test_case'
2
+
3
+ class TemOutputTest < TemTestCase
4
+ def test_output
5
+ sec = @tem.assemble { |s|
6
+ s.ldbc 32
7
+ s.outnew
8
+ s.outfxb :size => 3, :from => :area1
9
+ s.ldbc 5
10
+ s.outvlb :from => :area2
11
+ s.ldbc 4
12
+ s.ldwc :area3
13
+ s.outvb
14
+ s.ldwc 0x99AA - (1 << 16)
15
+ s.ldwc 0xFA55 - (1 << 16)
16
+ s.outb
17
+ s.outw
18
+ s.halt
19
+ s.label :area1
20
+ s.data :tem_ubyte, [0xFE, 0xCD, 0x9A]
21
+ s.label :area2
22
+ s.data :tem_ubyte, [0xAB, 0x95, 0xCE, 0xFD, 0x81]
23
+ s.label :area3
24
+ s.data :tem_ubyte, [0xEC, 0xDE, 0xAD, 0xCF]
25
+ s.stack 5
26
+ }
27
+ result = @tem.execute sec
28
+ assert_equal [0xFE, 0xCD, 0x9A, 0xAB, 0x95, 0xCE, 0xFD, 0x81, 0xEC, 0xDE,
29
+ 0xAD, 0xCF, 0x55, 0x99, 0xAA],
30
+ result, 'the output unit isn\'t working well'
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ require 'test/tem_test_case'
2
+
3
+ require 'test/tem_unit/test_tem_bound_secpack'
4
+ require 'test/tem_unit/test_tem_memory_compare'
5
+
6
+ class TemOutputTest < TemTestCase
7
+ include TemBoundSecpackTestCase
8
+ include TemMemoryCompareTestCase
9
+
10
+
11
+ def test_yaml_secpack
12
+ # simple test to ensure that the body is preserved
13
+ sec = @tem.assemble { |s|
14
+ s.ldbc 10
15
+ s.outnew
16
+ s.ldwc 0x1234
17
+ s.ldwc 0x5678
18
+ s.dupn :n => 2
19
+ s.add
20
+ s.outw
21
+ s.sub
22
+ s.outw
23
+ s.ldwc 0x0155
24
+ s.ldwc 0x02AA
25
+ s.mul
26
+ s.outw
27
+ s.ldwc 0x390C
28
+ s.ldwc 0x00AA
29
+ s.dupn :n => 2
30
+ s.div
31
+ s.outw
32
+ s.mod
33
+ s.outw
34
+ s.halt
35
+ s.stack 5
36
+ }
37
+ yaml_sec = sec.to_yaml_str
38
+ sec2 = Tem::SecPack.new_from_yaml_str(yaml_sec)
39
+ assert_equal sec.body, sec2.body,
40
+ 'SECpack body corrupted during serialization'
41
+
42
+ # re-run the memory test (reasonably large SECpack) to ensure that de-serialized SECpacks are equivalent to the originals
43
+ _test_memory_copy_compare true
44
+ # re-run the memory test (reasonably large SECpack) to ensure that serialization works on bound SECpacks
45
+ _test_bound_secpack true
46
+ end
47
+ end
@@ -0,0 +1,108 @@
1
+ require 'test/tem_test_case'
2
+
3
+ class DriverTest < TemTestCase
4
+ def test_buffers_io
5
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
6
+
7
+ bid = @tem.post_buffer garbage
8
+ assert_equal garbage.length, @tem.get_buffer_length(bid), 'error in posted buffer length'
9
+ assert_equal garbage, @tem.read_buffer(bid), 'error in posted buffer data'
10
+
11
+ garbage.reverse!
12
+ @tem.write_buffer bid, garbage
13
+ assert_equal garbage, @tem.read_buffer(bid), 'error in (reverted) posted buffer data'
14
+ @tem.release_buffer bid
15
+
16
+ @tem.post_buffer [1]
17
+ @tem.post_buffer [2]
18
+ @tem.flush_buffers
19
+ assert_equal 0, @tem.stat_buffers[:buffers].reject { |b| b[:free] }.length, 'flush_buffers left allocated buffers'
20
+ end
21
+
22
+ def test_buffers_alloc
23
+ b_lengths = [569, 231, 455, 18, 499, 332, 47]
24
+ b_ids = b_lengths.map { |len| @tem.alloc_buffer(len) }
25
+ bstat = @tem.stat_buffers
26
+
27
+ assert bstat[:free], 'buffer stat does not contain free memory information'
28
+ assert bstat[:free][:persistent].kind_of?(Numeric), 'buffer stat does not show free persistent memory'
29
+ assert bstat[:free][:persistent] >= 0, 'buffer stat shows negative free persistent memory'
30
+ assert bstat[:free][:clear_on_reset].kind_of?(Numeric), 'buffer stat does not show free clear_on_reset memory'
31
+ assert bstat[:free][:clear_on_reset] >= 0, 'buffer stat shows negative free clear_on_reset memory'
32
+ assert bstat[:free][:clear_on_deselect].kind_of?(Numeric), 'buffer stat does not show free clear_on_deselect memory'
33
+ assert bstat[:free][:clear_on_deselect] >= 0, 'buffer stat shows negative free clear_on_deselect memory'
34
+
35
+ b_lengths.each_index do |i|
36
+ assert bstat[:buffers][b_ids[i]], "buffer stat does not show an entry for a #{b_lengths[i]}-bytes buffer"
37
+ assert bstat[:buffers][b_ids[i]][:type].kind_of?(Symbol), "buffer stat does not show the memory type for a #{b_lengths[i]}-bytes buffer"
38
+ assert_equal b_lengths[i], bstat[:buffers][b_ids[i]][:length], "bad length in buffer stat entry for a #{b_lengths[i]}-bytes buffer"
39
+ assert_equal false, bstat[:buffers][b_ids[i]][:pinned], "bad pinned flag in buffer stat entry for a #{b_lengths[i]}-bytes buffer"
40
+ end
41
+
42
+ b_ids.each { |bid| @tem.release_buffer(bid) }
43
+ end
44
+
45
+ def test_tag
46
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
47
+
48
+ assert_raise(RuntimeError, 'tag returned before being set') { @tem.get_tag }
49
+
50
+ @tem.set_tag(garbage)
51
+ assert_equal garbage, @tem.get_tag[2..-1], 'error in posted tag data'
52
+
53
+ fwver = @tem.tk_firmware_ver
54
+ assert fwver[:major].kind_of?(Numeric) && fwver[:minor].kind_of?(Numeric), 'error in tag-backed firmware version'
55
+ end
56
+
57
+ def test_crypto
58
+ garbage = (1...415).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
59
+ key_pair = @tem.devchip_generate_key_pair
60
+ pubkey = @tem.devchip_save_key key_pair[:pubkey_id]
61
+
62
+ encrypted_garbage = @tem.devchip_encrypt garbage, key_pair[:privkey_id]
63
+ decrypted_garbage = pubkey.decrypt encrypted_garbage
64
+ assert_equal garbage, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
65
+
66
+ encrypted_garbage = pubkey.encrypt garbage
67
+ decrypted_garbage = @tem.devchip_decrypt encrypted_garbage, key_pair[:privkey_id]
68
+ assert_equal garbage, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
69
+
70
+ key_stat = @tem.stat_keys
71
+ assert key_stat[:keys], 'key stat does not contain key information'
72
+ assert_equal :public, key_stat[:keys][key_pair[:pubkey_id]][:type], 'key stat reports wrong type for public key'
73
+ assert_equal :private, key_stat[:keys][key_pair[:privkey_id]][:type], 'key stat reports wrong type for private key'
74
+ assert_in_delta 2, 2048, key_stat[:keys][key_pair[:pubkey_id]][:bits], 'key stat reports wrong size for public key'
75
+ assert_in_delta 2, 2048, key_stat[:keys][key_pair[:privkey_id]][:bits], 'key stat reports wrong size for private key'
76
+
77
+ [:pubkey_id, :privkey_id].each { |ki| @tem.devchip_release_key key_pair[ki] }
78
+ end
79
+
80
+ def test_crypto_abi
81
+ ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
82
+ pubk = Tem::Key.new_from_ssl_key ekey.public_key
83
+ privk = Tem::Key.new_from_ssl_key ekey
84
+
85
+ # array and string encryption/decryption
86
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
87
+ [garbage, garbage.pack('C*')].each do |g|
88
+ encrypted_garbage = pubk.encrypt g
89
+ decrypted_garbage = privk.decrypt encrypted_garbage
90
+ assert_equal g, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
91
+ encrypted_garbage = privk.encrypt g
92
+ decrypted_garbage = pubk.decrypt encrypted_garbage
93
+ assert_equal g, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
94
+ end
95
+
96
+ # test key serialization/deserialization through encryption/decryption
97
+ pubk_ys = pubk.to_yaml_str
98
+ pubk2 = Tem::Keys::Asymmetric.new_from_yaml_str(pubk_ys)
99
+ privk_ys = privk.to_yaml_str
100
+ privk2 = Tem::Keys::Asymmetric.new_from_yaml_str(privk_ys)
101
+ encrypted_garbage = pubk.encrypt garbage
102
+ decrypted_garbage = privk2.decrypt encrypted_garbage
103
+ assert_equal garbage, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
104
+ encrypted_garbage = privk.encrypt garbage
105
+ decrypted_garbage = pubk2.decrypt encrypted_garbage
106
+ assert_equal garbage, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
107
+ end
108
+ end
@@ -0,0 +1,35 @@
1
+ require 'test/tem_test_case'
2
+
3
+ class ExceptionsTest < TemTestCase
4
+ def test_trace
5
+ # test the exception handling mechanism
6
+ bad_sec = @tem.assemble { |s|
7
+ s.ldbc 2
8
+ s.outnew
9
+ s.ldbc 6
10
+ s.outw
11
+ # this exceeds the address space, so it should make the TEM die
12
+ s.ldwc 0x7fff
13
+ s.ldbv
14
+ s.label :bad_code
15
+ s.halt
16
+ s.label :stack
17
+ s.stack 5
18
+ }
19
+ assert_raise(Tem::SecExecError) { @tem.execute bad_sec }
20
+
21
+ caught = false
22
+ begin
23
+ @tem.execute bad_sec
24
+ rescue Tem::SecExecError => e
25
+ caught = true
26
+ assert_equal Hash, e.trace.class, "TEM exception does not have a TEM trace"
27
+ assert_equal 2, e.trace[:out], "Bad output buffer position in TEM trace"
28
+ assert_equal bad_sec.label_address(:bad_code), e.trace[:ip], "Bad instruction pointer in TEM trace"
29
+ assert_equal bad_sec.label_address(:stack), e.trace[:sp], "Bad instruction pointer in TEM trace"
30
+ assert_equal Hash, e.buffer_state.class, "TEM exception does not have buffer state information"
31
+ assert_equal Hash, e.key_state.class, "TEM exception does not have key state information"
32
+ end
33
+ assert caught, "Executing a bad SECpack did not raise a SecExecError"
34
+ end
35
+ end
@@ -0,0 +1,114 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'flexmock/test_unit'
5
+
6
+ require 'tem_ruby'
7
+
8
+ class AutoConfiguratorTest < Test::Unit::TestCase
9
+ AutoConfigurator = Tem::Transport::AutoConfigurator
10
+ PcscTransport = Tem::Transport::PcscTransport
11
+ JcopRemoteTransport = Tem::Transport::JcopRemoteTransport
12
+
13
+ def setup
14
+ @env_var = AutoConfigurator::ENVIRONMENT_VARIABLE_NAME
15
+ end
16
+
17
+ def test_env_configuration_blank
18
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return(nil)
19
+ assert_equal nil, AutoConfigurator.env_configuration
20
+ end
21
+ def test_env_configuration_remote_port
22
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return(':6996')
23
+ conf = AutoConfigurator.env_configuration
24
+ assert_equal JcopRemoteTransport, conf[:class]
25
+ assert_equal({:host => '127.0.0.1', :port => 6996}, conf[:opts])
26
+ end
27
+ def test_env_configuration_remote_noport
28
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return(':')
29
+ conf = AutoConfigurator.env_configuration
30
+ assert_equal JcopRemoteTransport, conf[:class]
31
+ assert_equal({:host => '127.0.0.1', :port => 8050}, conf[:opts])
32
+ end
33
+ def test_env_configuration_remote_host_port
34
+ flexmock(ENV).should_receive(:[]).with(@env_var).
35
+ and_return('@moonstone:6996')
36
+ conf = AutoConfigurator.env_configuration
37
+ assert_equal JcopRemoteTransport, conf[:class]
38
+ assert_equal({:host => 'moonstone', :port => 6996}, conf[:opts])
39
+ end
40
+ def test_env_configuration_remote_host_noport
41
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return('@moonstone')
42
+ conf = AutoConfigurator.env_configuration
43
+ assert_equal JcopRemoteTransport, conf[:class]
44
+ assert_equal({:host => 'moonstone', :port => 8050}, conf[:opts])
45
+ end
46
+ def test_env_configuration_remote_ipv6_port
47
+ flexmock(ENV).should_receive(:[]).with(@env_var).
48
+ and_return('@ff80::0080:6996')
49
+ conf = AutoConfigurator.env_configuration
50
+ assert_equal JcopRemoteTransport, conf[:class]
51
+ assert_equal({:host => 'ff80::0080', :port => 6996}, conf[:opts])
52
+ end
53
+ def test_env_configuration_remote_ipv6_noport
54
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return('@ff80::0080:')
55
+ conf = AutoConfigurator.env_configuration
56
+ assert_equal JcopRemoteTransport, conf[:class]
57
+ assert_equal({:host => 'ff80::0080', :port => 8050}, conf[:opts])
58
+ end
59
+
60
+ def test_env_configuration_pcsc_reader_index
61
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return('#1')
62
+ conf = AutoConfigurator.env_configuration
63
+ assert_equal PcscTransport, conf[:class]
64
+ assert_equal({:reader_index => 0}, conf[:opts])
65
+ end
66
+ def test_env_configuration_pcsc_reader_name
67
+ reader_name = 'Awesome Reader'
68
+ flexmock(ENV).should_receive(:[]).with(@env_var).
69
+ and_return(reader_name)
70
+ conf = AutoConfigurator.env_configuration
71
+ assert_equal PcscTransport, conf[:class]
72
+ assert_equal({:reader_name => reader_name}, conf[:opts])
73
+ end
74
+
75
+ def test_try_transport
76
+ transport = Object.new
77
+ flexmock(PcscTransport).should_receive(:new).with(:reader_index => 1).
78
+ and_return(transport)
79
+ flexmock(transport).should_receive(:connect)
80
+ flexmock(PcscTransport).should_receive(:new).with(:reader_index => 2).
81
+ and_raise('Boom headshot')
82
+ failport = Object.new
83
+ flexmock(PcscTransport).should_receive(:new).with(:reader_index => 3).
84
+ and_return(failport)
85
+ flexmock(failport).should_receive(:connect).and_raise('Lag')
86
+
87
+ config = { :class => PcscTransport, :opts => {:reader_index => 1} }
88
+ assert_equal transport, AutoConfigurator.try_transport(config)
89
+ config = { :class => PcscTransport, :opts => {:reader_index => 2} }
90
+ assert_equal nil, AutoConfigurator.try_transport(config)
91
+ config = { :class => PcscTransport, :opts => {:reader_index => 3} }
92
+ assert_equal nil, AutoConfigurator.try_transport(config)
93
+ end
94
+
95
+ def test_auto_transport_uses_env
96
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return('#1')
97
+ transport = Object.new
98
+ flexmock(PcscTransport).should_receive(:new).with(:reader_index => 0).
99
+ and_return(transport)
100
+ flexmock(transport).should_receive(:connect)
101
+
102
+ assert_equal transport, AutoConfigurator.auto_transport
103
+ end
104
+
105
+ def test_auto_transport_with_defaults
106
+ flexmock(ENV).should_receive(:[]).with(@env_var).and_return(nil)
107
+ transport = Object.new
108
+ flexmock(JcopRemoteTransport).should_receive(:new).and_return(nil)
109
+ flexmock(PcscTransport).should_receive(:new).and_return(transport)
110
+ flexmock(transport).should_receive(:connect)
111
+
112
+ assert_equal transport, AutoConfigurator.auto_transport
113
+ end
114
+ end
@@ -0,0 +1,90 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'flexmock/test_unit'
5
+
6
+ require 'tem_ruby'
7
+
8
+ class JavaCardMixinTest < Test::Unit::TestCase
9
+ JavaCardMixin = Tem::Transport::JavaCardMixin
10
+
11
+ # The sole purpose of this class is wrapping the mixin under test.
12
+ class MixinWrapper
13
+ include JavaCardMixin
14
+ end
15
+
16
+ def setup
17
+ end
18
+
19
+ def test_serialize_apdu
20
+ s = lambda { |apdu| JavaCardMixin.serialize_apdu apdu }
21
+
22
+ assert_equal [0x00, 0x05, 0x00, 0x00, 0x00], s[:ins => 0x05],
23
+ 'Specified INS'
24
+ assert_equal [0x00, 0x09, 0x00, 0x01, 0x00], s[:ins => 0x09, :p2 => 0x01],
25
+ 'Specified INS and P2'
26
+ assert_equal [0x00, 0xF9, 0xAC, 0xEF, 0x00],
27
+ s[:ins => 0xF9, :p1 => 0xAC, :p2 => 0xEF],
28
+ 'Specified INS, P1, P2'
29
+ assert_equal [0x00, 0xFA, 0xAD, 0xEC, 0x00],
30
+ s[:ins => 0xFA, :p12 => [0xAD, 0xEC]],
31
+ 'Specified INS, P1+P2'
32
+ assert_equal [0x00, 0x0E, 0x00, 0x00, 0x04, 0x33, 0x95, 0x81, 0x63],
33
+ s[:ins => 0x0E, :data => [0x33, 0x95, 0x81, 0x63]],
34
+ 'Specified INS and DATA'
35
+ assert_equal [0x80, 0x0F, 0xBA, 0xBE, 0x03, 0x31, 0x41, 0x59],
36
+ s[:cla => 0x80, :ins => 0x0F, :p1 => 0xBA, :p2 => 0xBE,
37
+ :data => [0x31, 0x41, 0x59]],
38
+ 'Specified everything'
39
+ assert_raise(RuntimeError, 'Did not specify INS') do
40
+ s[:cla => 0x80, :p1 => 0xBA, :p2 => 0xBE, :data => [0x31, 0x41, 0x59]]
41
+ end
42
+ end
43
+
44
+ def test_deserialize_response
45
+ d = lambda { |response| JavaCardMixin.deserialize_response response }
46
+
47
+ assert_equal({ :status => 0x9000, :data => [] }, d[[0x90, 0x00]])
48
+ assert_equal({ :status => 0x8631, :data => [] }, d[[0x86, 0x31]])
49
+ assert_equal({ :status => 0x9000, :data => [0x31, 0x41, 0x59, 0x26] },
50
+ d[[0x31, 0x41, 0x59, 0x26, 0x90, 0x00]])
51
+ assert_equal({ :status => 0x7395, :data => [0x31, 0x41, 0x59, 0x26] },
52
+ d[[0x31, 0x41, 0x59, 0x26, 0x73, 0x95]])
53
+ end
54
+
55
+ def win_mock
56
+ mock = MixinWrapper.new
57
+ flexmock(mock).should_receive(:exchange_apdu).
58
+ with([0x00, 0xF9, 0xAC, 0x00, 0x02, 0x31, 0x41]).
59
+ and_return([0x67, 0x31, 0x90, 0x00])
60
+ mock
61
+ end
62
+ def win_apdu
63
+ {:ins => 0xF9, :p1 => 0xAC, :data => [0x31, 0x41]}
64
+ end
65
+
66
+ def lose_mock
67
+ mock = MixinWrapper.new
68
+ flexmock(mock).should_receive(:exchange_apdu).
69
+ with([0x00, 0xF9, 0xAC, 0x00, 0x02, 0x31, 0x41]).
70
+ and_return([0x86, 0x31])
71
+ mock
72
+ end
73
+ def lose_apdu
74
+ win_apdu
75
+ end
76
+
77
+ def test_applet_apdu
78
+ assert_equal({:status => 0x9000, :data => [0x67, 0x31]},
79
+ win_mock.applet_apdu(win_apdu))
80
+ assert_equal({:status => 0x8631, :data => []},
81
+ lose_mock.applet_apdu(lose_apdu))
82
+ end
83
+
84
+ def test_applet_apdu_bang
85
+ assert_equal [0x67, 0x31], win_mock.applet_apdu!(win_apdu)
86
+ assert_raise(RuntimeError) do
87
+ lose_mock.applet_apdu!(lose_apdu)
88
+ end
89
+ end
90
+ end