tem_ruby 0.9.2 → 0.10.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.
@@ -0,0 +1,87 @@
1
+ require 'rubygems'
2
+ require 'smartcard'
3
+
4
+ # :nodoc: namespace
5
+ module Tem::Transport
6
+
7
+ class PcscTransport
8
+ include JavaCardMixin
9
+ PCSC = Smartcard::PCSC
10
+
11
+ def initialize(options)
12
+ @options = options
13
+ @context = nil
14
+ @card = nil
15
+ end
16
+
17
+ def exchange_apdu(apdu)
18
+ xmit_apdu_string = apdu.pack('C*')
19
+ result_string = @card.transmit xmit_apdu_string, @xmit_ioreq, @recv_ioreq
20
+ return result_string.unpack('C*')
21
+ end
22
+
23
+ def connect
24
+ @context = PCSC::Context.new(PCSC::SCOPE_SYSTEM) if @context.nil?
25
+
26
+ if @options[:reader_name]
27
+ @reader_name = reader_name
28
+ else
29
+ # get the first reader
30
+ readers = @context.list_readers nil
31
+ @reader_name = readers[@options[:reader_index] || 0]
32
+ end
33
+
34
+ # get the reader's status
35
+ reader_states = PCSC::ReaderStates.new(1)
36
+ reader_states.set_reader_name_of!(0, @reader_name)
37
+ reader_states.set_current_state_of!(0, PCSC::STATE_UNKNOWN)
38
+ @context.get_status_change reader_states, 100
39
+ reader_states.acknowledge_events!
40
+
41
+ # prompt for card insertion unless that already happened
42
+ if (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0
43
+ puts "Please insert TEM card in reader #{@reader_name}\n"
44
+ while (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0 do
45
+ @context.get_status_change reader_states, PCSC::INFINITE_TIMEOUT
46
+ reader_states.acknowledge_events!
47
+ end
48
+ puts "Card detected\n"
49
+ end
50
+
51
+ # connect to card
52
+ @card = PCSC::Card.new @context, @reader_name, PCSC::SHARE_EXCLUSIVE,
53
+ PCSC::PROTOCOL_ANY
54
+
55
+ # build the transmit / receive IoRequests
56
+ status = @card.status
57
+ @xmit_ioreq = @@xmit_iorequest[status[:protocol]]
58
+ if RUBY_PLATFORM =~ /win/ and (not RUBY_PLATFORM =~ /darwin/)
59
+ @recv_ioreq = nil
60
+ else
61
+ @recv_ioreq = PCSC::IoRequest.new
62
+ end
63
+ end
64
+
65
+ def disconnect
66
+ unless @card.nil?
67
+ @card.disconnect PCSC::DISPOSITION_LEAVE
68
+ @card = nil
69
+ end
70
+ unless @context.nil?
71
+ @context.release
72
+ @context = nil
73
+ end
74
+ end
75
+
76
+ def to_s
77
+ "#<PC/SC Terminal: disconnected>" if @card.nil?
78
+ "#<PC/SC Terminal: #{@reader_name}>"
79
+ end
80
+
81
+ @@xmit_iorequest = {
82
+ Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0,
83
+ Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1,
84
+ }
85
+ end # class PcscTransport
86
+
87
+ end # module Tem::Transport
@@ -0,0 +1,10 @@
1
+ # The transport module contains classes responsible for transferring low-level
2
+ # commands issed by the high-level TEM methods to actual TEMs, which can be
3
+ # connected to the system in various ways.
4
+ module Tem::Transport
5
+
6
+ # Shortcut for Tem::Transport::AutoConfigurator#auto_transport
7
+ def self.auto_transport
8
+ Tem::Transport::AutoConfigurator.auto_transport
9
+ end
10
+ end
data/lib/tem_ruby.rb CHANGED
@@ -1,17 +1,25 @@
1
1
  # gems
2
+ require 'rubygems'
2
3
  require 'smartcard'
3
4
 
5
+ # :nodoc:
4
6
  module Tem
5
7
  end
6
8
 
7
- module Tem::SCard
9
+ # :nodoc:
10
+ module Tem::Transport
8
11
  end
9
12
 
10
- require 'scard/pcsc_terminal.rb'
11
- require 'scard/jcop_remote_terminal.rb'
12
- require 'scard/java_card.rb'
13
+ require 'tem/transport/transport.rb'
14
+ require 'tem/transport/java_card_mixin.rb'
15
+ require 'tem/transport/pcsc_transport.rb'
16
+ require 'tem/transport/jcop_remote_protocol.rb'
17
+ require 'tem/transport/jcop_remote_transport.rb'
18
+ require 'tem/transport/jcop_remote_server.rb'
19
+ require 'tem/transport/auto_configurator.rb'
13
20
 
14
21
  require 'tem/abi.rb'
22
+ require 'tem/auto_conf.rb'
15
23
  require 'tem/buffers.rb'
16
24
  require 'tem/ca.rb'
17
25
  require 'tem/crypto_abi.rb'
data/tem_ruby.gemspec CHANGED
@@ -1,55 +1,39 @@
1
-
2
- # Gem::Specification for Tem_ruby-0.9.2
3
- # Originally generated by Echoe
1
+ # -*- encoding: utf-8 -*-
4
2
 
5
3
  Gem::Specification.new do |s|
6
4
  s.name = %q{tem_ruby}
7
- s.version = "0.9.2"
8
-
9
- s.specification_version = 2 if s.respond_to? :specification_version=
5
+ s.version = "0.10.0"
10
6
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
12
8
  s.authors = ["Victor Costan"]
13
- s.date = %q{2008-06-13}
9
+ s.date = %q{2009-04-08}
14
10
  s.description = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
15
11
  s.email = %q{victor@costan.us}
16
- s.executables = ["tem_stat", "tem_ca", "tem_irb", "tem_bench"]
17
- s.extra_rdoc_files = ["bin/tem_stat", "bin/tem_ca", "bin/tem_irb", "bin/tem_bench", "LICENSE", "lib/scard/java_card.rb", "lib/scard/jcop_remote_terminal.rb", "lib/scard/pcsc_terminal.rb", "lib/tem_ruby.rb", "lib/tem/tag.rb", "lib/tem/keys.rb", "lib/tem/sec_opcodes.rb", "lib/tem/_cert.rb", "lib/tem/buffers.rb", "lib/tem/toolkit.rb", "lib/tem/tem.rb", "lib/tem/abi.rb", "lib/tem/crypto_abi.rb", "lib/tem/ca.rb", "lib/tem/secpack.rb", "lib/tem/sec_exec_error.rb", "lib/tem/sec_assembler.rb", "lib/tem/lifecycle.rb", "lib/tem/ecert.rb", "lib/tem/hive.rb", "lib/tem/seclosures.rb", "README", "CHANGELOG"]
12
+ s.executables = ["tem_bench", "tem_ca", "tem_irb", "tem_proxy", "tem_stat"]
13
+ s.extra_rdoc_files = ["bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "CHANGELOG", "lib/tem/_cert.rb", "lib/tem/abi.rb", "lib/tem/auto_conf.rb", "lib/tem/buffers.rb", "lib/tem/ca.rb", "lib/tem/crypto_abi.rb", "lib/tem/ecert.rb", "lib/tem/hive.rb", "lib/tem/keys.rb", "lib/tem/lifecycle.rb", "lib/tem/sec_assembler.rb", "lib/tem/sec_exec_error.rb", "lib/tem/sec_opcodes.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tag.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem/transport/auto_configurator.rb", "lib/tem/transport/java_card_mixin.rb", "lib/tem/transport/jcop_remote_protocol.rb", "lib/tem/transport/jcop_remote_server.rb", "lib/tem/transport/jcop_remote_transport.rb", "lib/tem/transport/pcsc_transport.rb", "lib/tem/transport/transport.rb", "lib/tem_ruby.rb", "LICENSE", "README"]
14
+ s.files = ["bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "CHANGELOG", "dev_ca/ca_cert.cer", "dev_ca/ca_cert.pem", "dev_ca/ca_key.pem", "dev_ca/config.yml", "lib/tem/_cert.rb", "lib/tem/abi.rb", "lib/tem/auto_conf.rb", "lib/tem/buffers.rb", "lib/tem/ca.rb", "lib/tem/crypto_abi.rb", "lib/tem/ecert.rb", "lib/tem/hive.rb", "lib/tem/keys.rb", "lib/tem/lifecycle.rb", "lib/tem/sec_assembler.rb", "lib/tem/sec_exec_error.rb", "lib/tem/sec_opcodes.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tag.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem/transport/auto_configurator.rb", "lib/tem/transport/java_card_mixin.rb", "lib/tem/transport/jcop_remote_protocol.rb", "lib/tem/transport/jcop_remote_server.rb", "lib/tem/transport/jcop_remote_transport.rb", "lib/tem/transport/pcsc_transport.rb", "lib/tem/transport/transport.rb", "lib/tem_ruby.rb", "LICENSE", "Manifest", "Rakefile", "README", "test/_test_cert.rb", "test/tem_test_case.rb", "test/test_driver.rb", "test/test_exceptions.rb", "test/test_tem.rb", "test/transport/test_auto_configurator.rb", "test/transport/test_java_card_mixin.rb", "test/transport/test_jcop_remote.rb", "timings/blank_bound_secpack.rb", "timings/blank_sec.rb", "timings/devchip_decrypt.rb", "timings/post_buffer.rb", "timings/simple_apdu.rb", "timings/timings.rb", "timings/vm_perf.rb", "timings/vm_perf_bound.rb", "tem_ruby.gemspec"]
18
15
  s.has_rdoc = true
19
16
  s.homepage = %q{http://tem.rubyforge.org}
20
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tem_ruby", "--main", "README"]
21
18
  s.require_paths = ["lib"]
22
19
  s.rubyforge_project = %q{tem}
23
- s.rubygems_version = %q{1.1.1}
20
+ s.rubygems_version = %q{1.3.1}
24
21
  s.summary = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
25
- s.test_files = ["test/test_driver.rb", "test/test_tem.rb", "test/test_exceptions.rb"]
22
+ s.test_files = ["test/test_driver.rb", "test/test_exceptions.rb", "test/test_tem.rb", "test/transport/test_auto_configurator.rb", "test/transport/test_java_card_mixin.rb", "test/transport/test_jcop_remote.rb"]
26
23
 
27
- s.add_dependency(%q<smartcard>, [">= 0.3.0"])
28
- end
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
29
27
 
30
-
31
- # # Original Rakefile source (requires the Echoe gem):
32
- #
33
- # require 'rubygems'
34
- # gem 'echoe'
35
- # require 'echoe'
36
- #
37
- # Echoe.new('tem_ruby') do |p|
38
- # p.project = 'tem' # rubyforge project
39
- # p.docs_host = "costan@rubyforge.org:/var/www/gforge-projects/tem/rdoc/"
40
- #
41
- # p.author = 'Victor Costan'
42
- # p.email = 'victor@costan.us'
43
- # p.summary = 'TEM (Trusted Execution Module) driver, written in and for ruby.'
44
- # p.url = 'http://tem.rubyforge.org'
45
- # p.dependencies = ['smartcard >=0.3.0']
46
- #
47
- # p.need_tar_gz = true
48
- # p.need_zip = true
49
- # p.rdoc_pattern = /^(lib|bin|tasks|ext)|^BUILD|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
50
- # end
51
- #
52
- # if $0 == __FILE__
53
- # Rake.application = Rake::Application.new
54
- # Rake.application.run
55
- # end
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<smartcard>, [">= 0.3.0"])
30
+ s.add_development_dependency(%q<echoe>, [">= 0"])
31
+ else
32
+ s.add_dependency(%q<smartcard>, [">= 0.3.0"])
33
+ s.add_dependency(%q<echoe>, [">= 0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<smartcard>, [">= 0.3.0"])
37
+ s.add_dependency(%q<echoe>, [">= 0"])
38
+ end
39
+ end
data/test/_test_cert.rb CHANGED
@@ -26,23 +26,14 @@ require 'openssl'
26
26
 
27
27
  class CertTest < Test::Unit::TestCase
28
28
  def setup
29
- @terminal = Tem::SCard::JCOPRemoteTerminal.new
30
- unless @terminal.connect
31
- @terminal.disconnect
32
- @terminal = Tem::SCard::PCSCTerminal.new
33
- @terminal.connect
34
- end
35
- @javacard = Tem::SCard::JavaCard.new(@terminal)
36
- @tem = Tem::Session.new(@javacard)
29
+ @tem = Tem.auto_tem
37
30
 
38
31
  @tem.kill
39
32
  @tem.activate
40
-
41
-
42
33
  end
43
34
 
44
35
  def teardown
45
- @terminal.disconnect unless @terminal.nil?
36
+ @tem.disconnect unless @tem.nil?
46
37
  end
47
38
 
48
39
  def test_cert
@@ -75,7 +66,5 @@ class CertTest < Test::Unit::TestCase
75
66
  #The only way to set the signature is to sign the certificate, and only the issuer (manufacturer) can do this.
76
67
  #This means that the manufacturer has to be contacted every time the user wants to verify the TEM's certificate,
77
68
  #and this may not be practical.
78
-
79
-
80
69
  end
81
70
  end
@@ -0,0 +1,26 @@
1
+ require 'test/unit'
2
+
3
+ require 'tem_ruby'
4
+
5
+ # Helper methods for TEM tests.
6
+ #
7
+ # This module implements setup and teardown methods that provide an initialized
8
+ # @tem instance variable holding a Tem::Session. Just the right thing for
9
+ # testing :)
10
+ class TemTestCase < Test::Unit::TestCase
11
+ def setup
12
+ @tem = Tem.auto_tem
13
+
14
+ @tem.kill
15
+ @tem.activate
16
+ end
17
+
18
+ def teardown
19
+ @tem.disconnect unless @tem.nil?
20
+ end
21
+
22
+ def test_smoke
23
+ # All the required files have been parsed successfully.
24
+ assert true
25
+ end
26
+ end
data/test/test_driver.rb CHANGED
@@ -1,25 +1,6 @@
1
- require 'tem_ruby'
2
- require 'test/unit'
1
+ require 'test/tem_test_case'
3
2
 
4
- class DriverTest < 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
-
3
+ class DriverTest < TemTestCase
23
4
  def test_buffers_io
24
5
  garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
25
6
 
@@ -73,7 +54,7 @@ class DriverTest < Test::Unit::TestCase
73
54
  assert fwver[:major].kind_of?(Numeric) && fwver[:minor].kind_of?(Numeric), 'error in tag-backed firmware version'
74
55
  end
75
56
 
76
- def test_crypto
57
+ def test_crypto
77
58
  garbage = (1...415).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
78
59
  key_pair = @tem.devchip_generate_key_pair
79
60
  pubkey = @tem.devchip_save_key key_pair[:pubkey_id]
@@ -1,25 +1,6 @@
1
- require 'tem_ruby'
2
- require 'test/unit'
1
+ require 'test/tem_test_case'
3
2
 
4
- class ExceptionsTest < 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
-
3
+ class ExceptionsTest < TemTestCase
23
4
  def test_trace
24
5
  # test the exception handling mechanism
25
6
  bad_sec = @tem.assemble { |s|
@@ -52,4 +33,4 @@ class ExceptionsTest < Test::Unit::TestCase
52
33
  end
53
34
  assert caught, "Executing a bad SECpack did not raise a SecExecError"
54
35
  end
55
- end
36
+ end
data/test/test_tem.rb CHANGED
@@ -1,25 +1,6 @@
1
- require 'tem_ruby'
2
- require 'test/unit'
1
+ require 'test/tem_test_case'
3
2
 
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
-
3
+ class TemTest < TemTestCase
23
4
  def test_alu
24
5
  sec = @tem.assemble { |s|
25
6
  s.ldbc 10
@@ -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
@@ -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