smartcard 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ v0.2.2 Fixed APDU exchange bugs on Windows
2
+ Restructured PCSC::IoRequest to allow PCI_ consts
3
+ Added PCI_ consts
4
+ Changed test suite to reflect proper way to do transmits
5
+
1
6
  v0.2.1 Added OSX Tiger support
2
7
  Many workarounds for Tiger's buggy/incomplete PC/SC.
3
8
  Small bugfixes for PC/SC status constants.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2007 Victor Costan
3
+ Copyright (c) 2007 Massachusetts Institute of Technology
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README CHANGED
@@ -25,5 +25,8 @@ has the license in legalese.
25
25
 
26
26
  = Acknowledgements
27
27
 
28
- +smartcard+ is developed by Victor Costan while working as a Research Assistant for MIT.
29
- The work is sponsored by a grant from Quanta Computer Inc (www.quanta.com.tw)
28
+ +smartcard+ is developed by Victor Costan while working as a Research Assistant for MIT, under
29
+ {Prof. Srini Devadas}[http://people.csail.mit.edu/devadas/], in the
30
+ {Trusted Computing group}[http://projects.csail.mit.edu/tc/].
31
+ The work is funded by a grant from {Quanta Computer Inc}[http://www.quanta.com.tw], under the
32
+ {T-Party Project}[http://projects.csail.mit.edu/tparty/].
@@ -15,7 +15,7 @@ elsif RUBY_PLATFORM =~ /win/
15
15
  have_library('winscard')
16
16
  else
17
17
  # pcsc is retarded and uses stuff like '#include <wintypes.h>'
18
- $CFLAGS += ' -I /usr/include/PCSC -I /usr/local/include/pcsc'
18
+ $CFLAGS += ' -I /usr/include/PCSC -I /usr/local/include/PCSC'
19
19
  have_library('pcsclite')
20
20
  end
21
21
 
@@ -19,6 +19,7 @@ int _PCSC_ReaderStates_lowlevel_get(VALUE rbReaderStates, SCARD_READERSTATE **re
19
19
  extern VALUE cPcscIoRequest;
20
20
  void Init_PCSC_IoRequest();
21
21
  int _PCSC_IoRequest_lowlevel_get(VALUE rbIoRequest, SCARD_IO_REQUEST **io_request);
22
+ VALUE _PCSC_IoRequest_lowlevel_new(SCARD_IO_REQUEST *io_request);
22
23
 
23
24
  /* Class Smartcard::PCSC::Context */
24
25
  extern VALUE cPcscContext;
@@ -263,7 +263,7 @@ static VALUE PCSC_Card_set_attribute(VALUE self, VALUE rbAttributeId, VALUE rbAt
263
263
  * The bytes in the card's response are returned wrapped in a string. (don't complain, it's a low-level API)
264
264
  *
265
265
  * +send_data+:: the APDU to be send to the card; wrap the bytes in a string-like object (low-level API, remember?)
266
- * +send_io_request+:: Smartcard::PCSC::IoRequest instance indicating the send protocol; you can use one of the Smartcard::PCSC::PCI_ constants
266
+ * +send_io_request+:: Smartcard::PCSC::IoRequest instance indicating the send protocol; you should use one of the Smartcard::PCSC::IOREQUEST_ constants
267
267
  * +recv_io_request+:: Smartcard::PCSC::IoRequest instance receving information about the recv protocol; you can use the result of Smartcard::PCSC::IoRequest#new
268
268
  */
269
269
  static VALUE PCSC_Card_transmit(VALUE self, VALUE rbSendData, VALUE rbSendIoRequest, VALUE rbRecvIoRequest) {
@@ -186,10 +186,10 @@ void Init_PCSC_Consts() {
186
186
  /* SCARD_ATTR_MAXINPUT : Maximum size of an APDU supported by the reader. */
187
187
  rb_define_const(mPcsc, "ATTR_MAXINPUT", INT2NUM(SCARD_ATTR_MAXINPUT));
188
188
 
189
-
190
- /*
191
- #define SCARD_PCI_T0 (&g_rgSCardT0Pci)
192
- #define SCARD_PCI_T1 (&g_rgSCardT1Pci)
193
- #define SCARD_PCI_RAW (&g_rgSCardRawPci)
194
- */
195
- }
189
+ /* SCARD_PCI_T0 : IoRequest for transmitting using the T=0 protocol. */
190
+ rb_define_const(mPcsc, "IOREQUEST_T0", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_T0));
191
+ /* SCARD_PCI_T1 : IoRequest for transmitting using the T=1 protocol. */
192
+ rb_define_const(mPcsc, "IOREQUEST_T1", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_T1));
193
+ /* SCARD_PCI_RAW : IoRequest for transmitting using the RAW protocol. */
194
+ rb_define_const(mPcsc, "IOREQUEST_RAW", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_RAW));
195
+ }
@@ -2,20 +2,48 @@
2
2
 
3
3
  VALUE cPcscIoRequest;
4
4
 
5
+ /* Wraps a SCARD_IO_REQUEST, tracking its allocation etc. */
6
+ struct SCardIoRequestEx {
7
+ SCARD_IO_REQUEST *pcsc_request;
8
+ int mallocd;
9
+ };
10
+
5
11
  /* Custom free for Smartcard::PCSC::IoRequest. */
6
- static void PCSC_IoRequest_free(SCARD_IO_REQUEST *_request) {
7
- if(_request != NULL)
12
+ static void PCSC_IoRequest_free(struct SCardIoRequestEx *_request) {
13
+ if(_request != NULL) {
14
+ if(_request->mallocd)
15
+ xfree(_request->pcsc_request);
8
16
  xfree(_request);
17
+ }
9
18
  }
10
19
 
11
- /* Custom allocation for Smartcard::PCSC::Card. Wraps a SCARD_IO_REQUEST. */
20
+ /* Custom allocation for Smartcard::PCSC::Card. Wraps a SCardIoRequestEx. */
12
21
  static VALUE PCSC_IoRequest_alloc(VALUE klass) {
13
- SCARD_IO_REQUEST *request;
22
+ struct SCardIoRequestEx *request;
14
23
 
15
- VALUE rbIoRequest = Data_Make_Struct(klass, SCARD_IO_REQUEST, NULL, PCSC_IoRequest_free, request);
24
+ VALUE rbIoRequest = Data_Make_Struct(klass, struct SCardIoRequestEx, NULL, PCSC_IoRequest_free, request);
25
+ request->pcsc_request = NULL;
26
+ request->mallocd = 0;
16
27
  return rbIoRequest;
17
28
  }
18
29
 
30
+ /* :Document-method: new
31
+ * call-seq:
32
+ * new() --> io_request
33
+ *
34
+ * Creates an uninitialized IoRequest.
35
+ * The request can be used as a receiving IoRequest in Smartcard::PCSC::Card#transmit.
36
+ */
37
+ static VALUE PCSC_IoRequest_initialize(VALUE self) {
38
+ struct SCardIoRequestEx *request;
39
+
40
+ Data_Get_Struct(self, struct SCardIoRequestEx, request);
41
+ request->pcsc_request = ALLOC(SCARD_IO_REQUEST);
42
+ request->mallocd = 1;
43
+
44
+ return self;
45
+ }
46
+
19
47
  /* :Document-method: protocol
20
48
  * call-seq:
21
49
  * io_request.protocol --> protocol
@@ -25,12 +53,12 @@ static VALUE PCSC_IoRequest_alloc(VALUE klass) {
25
53
  * The returned protocol is a number, and should be checked against one of the Smartcard::PCSC::PROTOCOL_ constants.
26
54
  */
27
55
  static VALUE PCSC_IoRequest_get_protocol(VALUE self) {
28
- SCARD_IO_REQUEST *request;
56
+ struct SCardIoRequestEx *request;
29
57
 
30
- Data_Get_Struct(self, SCARD_IO_REQUEST, request);
58
+ Data_Get_Struct(self, struct SCardIoRequestEx, request);
31
59
  if(request == NULL) return Qnil;
32
60
 
33
- return UINT2NUM(request->dwProtocol);
61
+ return UINT2NUM(request->pcsc_request->dwProtocol);
34
62
  }
35
63
 
36
64
  /* :Document-method: protocol=
@@ -42,12 +70,15 @@ static VALUE PCSC_IoRequest_get_protocol(VALUE self) {
42
70
  * +protocol+:: use one of the Smartcard::PCSC::PROTOCOL_ constants
43
71
  */
44
72
  static VALUE PCSC_IoRequest_set_protocol(VALUE self, VALUE rbProtocol) {
45
- SCARD_IO_REQUEST *request;
73
+ struct SCardIoRequestEx *request;
46
74
 
47
- Data_Get_Struct(self, SCARD_IO_REQUEST, request);
75
+ Data_Get_Struct(self, struct SCardIoRequestEx, request);
48
76
  if(request == NULL) return self;
49
77
 
50
- request->dwProtocol = NUM2UINT(rbProtocol);
78
+ if(request->mallocd == 0)
79
+ rb_raise(rb_eSecurityError, "cannot modify PC/SC-global (read-only) IO_REQUEST");
80
+ else
81
+ request->pcsc_request->dwProtocol = NUM2UINT(rbProtocol);
51
82
  return self;
52
83
  }
53
84
 
@@ -66,13 +97,14 @@ static VALUE PCSC_IoRequest_set_protocol(VALUE self, VALUE rbProtocol) {
66
97
  void Init_PCSC_IoRequest() {
67
98
  cPcscIoRequest = rb_define_class_under(mPcsc, "IoRequest", rb_cObject);
68
99
  rb_define_alloc_func(cPcscIoRequest, PCSC_IoRequest_alloc);
100
+ rb_define_method(cPcscIoRequest, "initialize", PCSC_IoRequest_initialize, 0);
69
101
  rb_define_method(cPcscIoRequest, "protocol", PCSC_IoRequest_get_protocol, 0);
70
102
  rb_define_method(cPcscIoRequest, "protocol=", PCSC_IoRequest_set_protocol, 1);
71
103
  }
72
104
 
73
105
  /* Retrieves the SCARD_IO_REQUEST wrapped into a Smartcard::PCSC::IoRequest instance. */
74
106
  int _PCSC_IoRequest_lowlevel_get(VALUE rbIoRequest, SCARD_IO_REQUEST **io_request) {
75
- SCARD_IO_REQUEST *request;
107
+ struct SCardIoRequestEx *request;
76
108
 
77
109
  if(TYPE(rbIoRequest) == T_NIL || TYPE(rbIoRequest) == T_FALSE) {
78
110
  *io_request = NULL;
@@ -81,7 +113,17 @@ int _PCSC_IoRequest_lowlevel_get(VALUE rbIoRequest, SCARD_IO_REQUEST **io_reques
81
113
  if(TYPE(rbIoRequest) != T_DATA || RDATA(rbIoRequest)->dfree != (void (*)(void *))PCSC_IoRequest_free)
82
114
  return 0;
83
115
 
84
- Data_Get_Struct(rbIoRequest, SCARD_IO_REQUEST, request);
85
- *io_request = request;
116
+ Data_Get_Struct(rbIoRequest, struct SCardIoRequestEx, request);
117
+ *io_request = request->pcsc_request;
86
118
  return 1;
87
119
  }
120
+
121
+ /* Creates a Smartcard::PCSC::IoRequest instance wrapping a given SCARD_IO_REQUEST. */
122
+ VALUE _PCSC_IoRequest_lowlevel_new(SCARD_IO_REQUEST *io_request) {
123
+ struct SCardIoRequestEx *request;
124
+
125
+ VALUE rbIoRequest = Data_Make_Struct(cPcscIoRequest, struct SCardIoRequestEx, NULL, PCSC_IoRequest_free, request);
126
+ request->pcsc_request = io_request;
127
+ request->mallocd = 0;
128
+ return rbIoRequest;
129
+ }
@@ -7,4 +7,4 @@ void Init_pcsc() {
7
7
  Init_PCSC_Context();
8
8
  Init_PCSC_Card();
9
9
  Init_PCSC_Consts();
10
- }
10
+ }
@@ -79,4 +79,4 @@ char *pcsc_stringify_error(DWORD scard_error) {
79
79
  scard_error_buffer, sizeof(scard_error_buffer), NULL );
80
80
  return scard_error_buffer;
81
81
  }
82
- #endif
82
+ #endif
data/smartcard.gemspec CHANGED
@@ -1,30 +1,35 @@
1
1
 
2
- # Gem::Specification for Smartcard-0.2.1
2
+ # Gem::Specification for Smartcard-0.2.2
3
3
  # Originally generated by Echoe
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{smartcard}
7
- s.version = "0.2.1"
8
- s.date = %q{2007-11-19}
9
- s.summary = %q{Interface with ISO 7816 smart cards.}
10
- s.require_paths = ["lib", "ext"]
7
+ s.version = "0.2.2"
8
+
9
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Victor Costan"]
13
+ s.date = %q{2007-11-28}
14
+ s.description = %q{Interface with ISO 7816 smart cards.}
11
15
  s.email = %q{victor@costan.us}
16
+ s.extensions = ["ext/smartcard_pcsc/extconf.rb"]
17
+ s.files = ["BUILD", "CHANGELOG", "ext/smartcard_pcsc/extconf.rb", "ext/smartcard_pcsc/pcsc.h", "ext/smartcard_pcsc/pcsc_card.c", "ext/smartcard_pcsc/pcsc_constants.c", "ext/smartcard_pcsc/pcsc_context.c", "ext/smartcard_pcsc/pcsc_io_request.c", "ext/smartcard_pcsc/pcsc_main.c", "ext/smartcard_pcsc/pcsc_multi_strings.c", "ext/smartcard_pcsc/pcsc_namespace.c", "ext/smartcard_pcsc/pcsc_reader_states.c", "ext/smartcard_pcsc/pcsc_surrogate_reader.h", "ext/smartcard_pcsc/pcsc_surrogate_wintypes.h", "lib/smartcard.rb", "LICENSE", "Manifest", "README", "test/test_all.rb", "tests/ts_pcsc_ext.rb", "smartcard.gemspec"]
18
+ s.has_rdoc = true
12
19
  s.homepage = %q{http://www.costan.us/smartcard}
20
+ s.require_paths = ["lib", "ext"]
13
21
  s.rubyforge_project = %q{smartcard}
14
- s.description = %q{Interface with ISO 7816 smart cards.}
15
- s.has_rdoc = true
16
- s.authors = ["Victor Costan"]
17
- s.files = ["BUILD", "CHANGELOG", "ext/smartcard_pcsc/extconf.rb", "ext/smartcard_pcsc/pcsc.h", "ext/smartcard_pcsc/pcsc_card.c", "ext/smartcard_pcsc/pcsc_constants.c", "ext/smartcard_pcsc/pcsc_context.c", "ext/smartcard_pcsc/pcsc_io_request.c", "ext/smartcard_pcsc/pcsc_main.c", "ext/smartcard_pcsc/pcsc_multi_strings.c", "ext/smartcard_pcsc/pcsc_namespace.c", "ext/smartcard_pcsc/pcsc_reader_states.c", "ext/smartcard_pcsc/pcsc_surrogate_reader.h", "ext/smartcard_pcsc/pcsc_surrogate_wintypes.h", "lib/smartcard.rb", "LICENSE", "Manifest", "README", "test/test_all.rb", "tests/ts_pcsc_ext.rb", "smartcard.gemspec"]
22
+ s.rubygems_version = %q{0.9.5}
23
+ s.summary = %q{Interface with ISO 7816 smart cards.}
18
24
  s.test_files = ["test/test_all.rb"]
19
- s.extensions = ["ext/smartcard_pcsc/extconf.rb"]
20
25
  end
21
26
 
22
27
 
23
28
  # # Original Rakefile source (requires the Echoe gem):
24
29
  #
25
- # # Needs the 'echoe' gem
30
+ # require 'rubygems'
31
+ # gem 'echoe'
26
32
  # require 'echoe'
27
- # require 'pp'
28
33
  #
29
34
  # Echoe.new('smartcard') do |p|
30
35
  # p.project = 'smartcard' # rubyforge project
@@ -52,4 +57,9 @@ end
52
57
  # task :package => [ :clean, :compile, :postcompile_hacks ]
53
58
  # end
54
59
  # end
60
+ # end
61
+ #
62
+ # if $0 == __FILE__
63
+ # Rake.application = Rake::Application.new
64
+ # Rake.application.run
55
65
  # end
data/tests/ts_pcsc_ext.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'rubygems'
2
+ gem 'smartcard', '>= 0.2.1'
1
3
  require 'smartcard'
2
4
  require 'pp'
3
5
 
@@ -57,7 +59,7 @@ def test_io_request
57
59
  io_request = Smartcard::PCSC::IoRequest.new
58
60
  [Smartcard::PCSC::PROTOCOL_T0, Smartcard::PCSC::PROTOCOL_T1, Smartcard::PCSC::PROTOCOL_RAW].each do |t_protocol|
59
61
  io_request.protocol = t_protocol
60
- r_protocol = io_request.protocol
62
+ r_protocol = io_request.protocol
61
63
  if r_protocol != t_protocol
62
64
  puts "FAILED: IoRequest.protocol= / protocol failed for protocol #{t_protocol} (got #{r_protocol} instead)\n"
63
65
  return false
@@ -116,9 +118,10 @@ rescue RuntimeError => e
116
118
  end
117
119
 
118
120
  puts "Selecting applet\n"
119
- aid = [0x19, 0x83, 0x12, 0x29, 0xba, 0xbe]
121
+ aid = [0x19, 0x83, 0x12, 0x29, 0x10, 0xba, 0xbe]
120
122
  select_apdu = [0x00, 0xA4, 0x04, 0x00, aid.length, aid].flatten
121
- send_ioreq = Smartcard::PCSC::IoRequest.new; send_ioreq.protocol = Smartcard::PCSC::PROTOCOL_T1;
123
+ send_ioreq = {Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0,
124
+ Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1}[card_status[:protocol]]
122
125
  recv_ioreq = Smartcard::PCSC::IoRequest.new
123
126
  select_response = card0.transmit(select_apdu.map {|byte| byte.chr}.join(''), send_ioreq, recv_ioreq)
124
127
  select_response_str = (0...select_response.length).map { |i| ' %02x' % select_response[i].to_i }.join('')
metadata CHANGED
@@ -1,34 +1,26 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: smartcard
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.2.1
7
- date: 2007-11-19 00:00:00 -05:00
8
- summary: Interface with ISO 7816 smart cards.
9
- require_paths:
10
- - lib
11
- - ext
12
- email: victor@costan.us
13
- homepage: http://www.costan.us/smartcard
14
- rubyforge_project: smartcard
15
- description: Interface with ISO 7816 smart cards.
16
- autorequire:
17
- default_executable:
18
- bindir: bin
19
- has_rdoc: true
20
- required_ruby_version: !ruby/object:Gem::Version::Requirement
21
- requirements:
22
- - - ">"
23
- - !ruby/object:Gem::Version
24
- version: 0.0.0
25
- version:
4
+ version: 0.2.2
26
5
  platform: ruby
27
- signing_key:
28
- cert_chain:
29
- post_install_message:
30
6
  authors:
31
7
  - Victor Costan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2007-11-28 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Interface with ISO 7816 smart cards.
17
+ email: victor@costan.us
18
+ executables: []
19
+
20
+ extensions:
21
+ - ext/smartcard_pcsc/extconf.rb
22
+ extra_rdoc_files: []
23
+
32
24
  files:
33
25
  - BUILD
34
26
  - CHANGELOG
@@ -51,17 +43,32 @@ files:
51
43
  - test/test_all.rb
52
44
  - tests/ts_pcsc_ext.rb
53
45
  - smartcard.gemspec
54
- test_files:
55
- - test/test_all.rb
46
+ has_rdoc: true
47
+ homepage: http://www.costan.us/smartcard
48
+ post_install_message:
56
49
  rdoc_options: []
57
50
 
58
- extra_rdoc_files: []
59
-
60
- executables: []
61
-
62
- extensions:
63
- - ext/smartcard_pcsc/extconf.rb
51
+ require_paths:
52
+ - lib
53
+ - ext
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
64
66
  requirements: []
65
67
 
66
- dependencies: []
67
-
68
+ rubyforge_project: smartcard
69
+ rubygems_version: 0.9.5
70
+ signing_key:
71
+ specification_version: 2
72
+ summary: Interface with ISO 7816 smart cards.
73
+ test_files:
74
+ - test/test_all.rb