tem_ruby 0.9.2 → 0.10.0

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