smartcard 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/smartcard_pcsc/extconf.rb +22 -0
- data/ext/smartcard_pcsc/pcsc.h +35 -0
- data/ext/smartcard_pcsc/pcsc_card.c +440 -0
- data/ext/smartcard_pcsc/pcsc_constants.c +189 -0
- data/ext/smartcard_pcsc/pcsc_context.c +275 -0
- data/ext/smartcard_pcsc/pcsc_io_request.c +84 -0
- data/ext/smartcard_pcsc/pcsc_main.c +10 -0
- data/ext/smartcard_pcsc/pcsc_multi_strings.c +65 -0
- data/ext/smartcard_pcsc/pcsc_namespace.c +18 -0
- data/ext/smartcard_pcsc/pcsc_reader_states.c +313 -0
- data/ext/smartcard_pcsc/pcsc_surrogate_reader.h +207 -0
- data/ext/smartcard_pcsc/pcsc_surrogate_wintypes.h +63 -0
- data/lib/smartcard.rb +1 -0
- data/tests/ts_pcsc_ext.rb +130 -0
- metadata +60 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
/*
|
2
|
+
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
|
3
|
+
*
|
4
|
+
* Copyright (C) 1999-2005
|
5
|
+
* David Corcoran <corcoran@linuxnet.com>
|
6
|
+
* Ludovic Rousseau <ludovic.rousseau@free.fr>
|
7
|
+
*
|
8
|
+
* $Id: reader.h.in 2572 2007-06-20 07:24:35Z rousseau $
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @file
|
13
|
+
* @brief This keeps a list of defines shared between the driver and the application
|
14
|
+
*/
|
15
|
+
|
16
|
+
#ifndef __reader_h__
|
17
|
+
#define __reader_h__
|
18
|
+
|
19
|
+
/*
|
20
|
+
* Tags for requesting card and reader attributes
|
21
|
+
*/
|
22
|
+
|
23
|
+
#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
|
24
|
+
|
25
|
+
#define SCARD_CLASS_VENDOR_INFO 1 /**< Vendor information definitions */
|
26
|
+
#define SCARD_CLASS_COMMUNICATIONS 2 /**< Communication definitions */
|
27
|
+
#define SCARD_CLASS_PROTOCOL 3 /**< Protocol definitions */
|
28
|
+
#define SCARD_CLASS_POWER_MGMT 4 /**< Power Management definitions */
|
29
|
+
#define SCARD_CLASS_SECURITY 5 /**< Security Assurance definitions */
|
30
|
+
#define SCARD_CLASS_MECHANICAL 6 /**< Mechanical characteristic definitions */
|
31
|
+
#define SCARD_CLASS_VENDOR_DEFINED 7 /**< Vendor specific definitions */
|
32
|
+
#define SCARD_CLASS_IFD_PROTOCOL 8 /**< Interface Device Protocol options */
|
33
|
+
#define SCARD_CLASS_ICC_STATE 9 /**< ICC State specific definitions */
|
34
|
+
#define SCARD_CLASS_SYSTEM 0x7fff /**< System-specific definitions */
|
35
|
+
|
36
|
+
#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100)
|
37
|
+
#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101)
|
38
|
+
#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102)
|
39
|
+
#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103)
|
40
|
+
#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110)
|
41
|
+
#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120)
|
42
|
+
#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121)
|
43
|
+
#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122)
|
44
|
+
#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123)
|
45
|
+
#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124)
|
46
|
+
#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125)
|
47
|
+
#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126)
|
48
|
+
#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131)
|
49
|
+
#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140)
|
50
|
+
#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142)
|
51
|
+
#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150)
|
52
|
+
|
53
|
+
#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201)
|
54
|
+
#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202)
|
55
|
+
#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203)
|
56
|
+
#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204)
|
57
|
+
#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205)
|
58
|
+
#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206)
|
59
|
+
#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207)
|
60
|
+
#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208)
|
61
|
+
#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209)
|
62
|
+
#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a)
|
63
|
+
#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b)
|
64
|
+
#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c)
|
65
|
+
|
66
|
+
#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300)
|
67
|
+
#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301)
|
68
|
+
#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302)
|
69
|
+
#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
|
70
|
+
#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304)
|
71
|
+
|
72
|
+
#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000)
|
73
|
+
#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003)
|
74
|
+
#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005)
|
75
|
+
#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007)
|
76
|
+
|
77
|
+
#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001)
|
78
|
+
#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002)
|
79
|
+
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
|
80
|
+
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004)
|
81
|
+
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
|
82
|
+
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006)
|
83
|
+
#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007)
|
84
|
+
|
85
|
+
#ifdef UNICODE
|
86
|
+
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W
|
87
|
+
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W
|
88
|
+
#else
|
89
|
+
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A
|
90
|
+
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A
|
91
|
+
#endif
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Provide source compatibility on different platforms
|
95
|
+
*/
|
96
|
+
#define SCARD_CTL_CODE(code) (0x42000000 + (code))
|
97
|
+
|
98
|
+
/**
|
99
|
+
* TeleTrust Class 2 reader tags
|
100
|
+
*/
|
101
|
+
#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
|
102
|
+
|
103
|
+
#define FEATURE_VERIFY_PIN_START 0x01 /**< OMNIKEY Proposal */
|
104
|
+
#define FEATURE_VERIFY_PIN_FINISH 0x02 /**< OMNIKEY Proposal */
|
105
|
+
#define FEATURE_MODIFY_PIN_START 0x03 /**< OMNIKEY Proposal */
|
106
|
+
#define FEATURE_MODIFY_PIN_FINISH 0x04 /**< OMNIKEY Proposal */
|
107
|
+
#define FEATURE_GET_KEY_PRESSED 0x05 /**< OMNIKEY Proposal */
|
108
|
+
#define FEATURE_VERIFY_PIN_DIRECT 0x06 /**< USB CCID PIN Verify */
|
109
|
+
#define FEATURE_MODIFY_PIN_DIRECT 0x07 /**< USB CCID PIN Modify */
|
110
|
+
#define FEATURE_MCT_READERDIRECT 0x08 /**< KOBIL Proposal */
|
111
|
+
#define FEATURE_MCT_UNIVERSAL 0x09 /**< KOBIL Proposal */
|
112
|
+
#define FEATURE_IFD_PIN_PROP 0x0A /**< Gemplus Proposal */
|
113
|
+
#define FEATURE_ABORT 0x0B /**< SCM Proposal */
|
114
|
+
|
115
|
+
/* structures used (but not defined) in PCSC Part 10 revision 2.01.02:
|
116
|
+
* "IFDs with Secure Pin Entry Capabilities" */
|
117
|
+
|
118
|
+
#include <inttypes.h>
|
119
|
+
|
120
|
+
/* Set structure elements aligment on bytes
|
121
|
+
* http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
|
122
|
+
#if defined(__APPLE__) | defined(sun)
|
123
|
+
#pragma pack(1)
|
124
|
+
#else
|
125
|
+
#pragma pack(push, 1)
|
126
|
+
#endif
|
127
|
+
|
128
|
+
/** the structure must be 6-bytes long */
|
129
|
+
typedef struct
|
130
|
+
{
|
131
|
+
uint8_t tag;
|
132
|
+
uint8_t length;
|
133
|
+
uint32_t value; /**< This value is always in BIG ENDIAN format as documented in PCSC v2 part 10 ch 2.2 page 2. You can use ntohl() for example */
|
134
|
+
} PCSC_TLV_STRUCTURE;
|
135
|
+
|
136
|
+
/** the wLangId and wPINMaxExtraDigit are 16-bits long so are subject to byte
|
137
|
+
* ordering */
|
138
|
+
#define HOST_TO_CCID_16(x) @host_to_ccid_16@
|
139
|
+
#define HOST_TO_CCID_32(x) @host_to_ccid_32@
|
140
|
+
|
141
|
+
/** structure used with \ref FEATURE_VERIFY_PIN_DIRECT */
|
142
|
+
typedef struct
|
143
|
+
{
|
144
|
+
uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
|
145
|
+
uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
|
146
|
+
uint8_t bmFormatString; /**< formatting options */
|
147
|
+
uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
|
148
|
+
* bits 3-0 PIN block size in bytes after
|
149
|
+
* justification and formatting */
|
150
|
+
uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
|
151
|
+
* bit 4 set if system units are bytes, clear if
|
152
|
+
* system units are bits,
|
153
|
+
* bits 3-0 PIN length position in system units */
|
154
|
+
uint16_t wPINMaxExtraDigit; /**< 0xXXYY where XX is minimum PIN size in digits,
|
155
|
+
and YY is maximum PIN size in digits */
|
156
|
+
uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
|
157
|
+
* be considered complete */
|
158
|
+
uint8_t bNumberMessage; /**< Number of messages to display for PIN verification */
|
159
|
+
uint16_t wLangId; /**< Language for messages */
|
160
|
+
uint8_t bMsgIndex; /**< Message index (should be 00) */
|
161
|
+
uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
|
162
|
+
uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
|
163
|
+
uint8_t abData[1]; /**< Data to send to the ICC */
|
164
|
+
} PIN_VERIFY_STRUCTURE;
|
165
|
+
|
166
|
+
/** structure used with \ref FEATURE_MODIFY_PIN_DIRECT */
|
167
|
+
typedef struct
|
168
|
+
{
|
169
|
+
uint8_t bTimerOut; /**< timeout is seconds (00 means use default timeout) */
|
170
|
+
uint8_t bTimerOut2; /**< timeout in seconds after first key stroke */
|
171
|
+
uint8_t bmFormatString; /**< formatting options */
|
172
|
+
uint8_t bmPINBlockString; /**< bits 7-4 bit size of PIN length in APDU,
|
173
|
+
* bits 3-0 PIN block size in bytes after
|
174
|
+
* justification and formatting */
|
175
|
+
uint8_t bmPINLengthFormat; /**< bits 7-5 RFU,
|
176
|
+
* bit 4 set if system units are bytes, clear if
|
177
|
+
* system units are bits,
|
178
|
+
* bits 3-0 PIN length position in system units */
|
179
|
+
uint8_t bInsertionOffsetOld; /**< Insertion position offset in bytes for
|
180
|
+
the current PIN */
|
181
|
+
uint8_t bInsertionOffsetNew; /**< Insertion position offset in bytes for
|
182
|
+
the new PIN */
|
183
|
+
uint16_t wPINMaxExtraDigit;
|
184
|
+
/**< 0xXXYY where XX is minimum PIN size in digits,
|
185
|
+
and YY is maximum PIN size in digits */
|
186
|
+
uint8_t bConfirmPIN; /**< Flags governing need for confirmation of new PIN */
|
187
|
+
uint8_t bEntryValidationCondition; /**< Conditions under which PIN entry should
|
188
|
+
* be considered complete */
|
189
|
+
uint8_t bNumberMessage; /**< Number of messages to display for PIN verification*/
|
190
|
+
uint16_t wLangId; /**< Language for messages */
|
191
|
+
uint8_t bMsgIndex1; /**< index of 1st prompting message */
|
192
|
+
uint8_t bMsgIndex2; /**< index of 2d prompting message */
|
193
|
+
uint8_t bMsgIndex3; /**< index of 3d prompting message */
|
194
|
+
uint8_t bTeoPrologue[3]; /**< T=1 block prologue field to use (fill with 00) */
|
195
|
+
uint32_t ulDataLength; /**< length of Data to be sent to the ICC */
|
196
|
+
uint8_t abData[1]; /**< Data to send to the ICC */
|
197
|
+
} PIN_MODIFY_STRUCTURE;
|
198
|
+
|
199
|
+
/* restore default structure elements alignment */
|
200
|
+
#if defined(__APPLE__) | defined(sun)
|
201
|
+
#pragma pack()
|
202
|
+
#else
|
203
|
+
#pragma pack(pop)
|
204
|
+
#endif
|
205
|
+
|
206
|
+
#endif
|
207
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/*
|
2
|
+
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
|
3
|
+
*
|
4
|
+
* Copyright (C) 1999
|
5
|
+
* David Corcoran <corcoran@linuxnet.com>
|
6
|
+
*
|
7
|
+
* $Id: wintypes.h 2537 2007-05-22 15:02:26Z rousseau $
|
8
|
+
*/
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @file
|
12
|
+
* @brief This keeps a list of Windows(R) types.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#ifndef __wintypes_h__
|
16
|
+
#define __wintypes_h__
|
17
|
+
|
18
|
+
#ifdef __cplusplus
|
19
|
+
extern "C"
|
20
|
+
{
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#if !defined(WIN32)
|
24
|
+
|
25
|
+
#ifndef BYTE
|
26
|
+
typedef unsigned char BYTE;
|
27
|
+
#endif
|
28
|
+
typedef unsigned char UCHAR;
|
29
|
+
typedef unsigned char *PUCHAR;
|
30
|
+
typedef unsigned short USHORT;
|
31
|
+
|
32
|
+
#ifndef __COREFOUNDATION_CFPLUGINCOM__
|
33
|
+
typedef unsigned long ULONG;
|
34
|
+
typedef void *LPVOID;
|
35
|
+
typedef short BOOL;
|
36
|
+
#endif
|
37
|
+
|
38
|
+
typedef unsigned long *PULONG;
|
39
|
+
typedef const void *LPCVOID;
|
40
|
+
typedef uint32_t DWORD;
|
41
|
+
typedef uint32_t *PDWORD;
|
42
|
+
typedef uint16_t WORD;
|
43
|
+
typedef long LONG;
|
44
|
+
typedef const char *LPCSTR;
|
45
|
+
typedef const BYTE *LPCBYTE;
|
46
|
+
typedef BYTE *LPBYTE;
|
47
|
+
typedef DWORD *LPDWORD;
|
48
|
+
typedef unsigned char *LPSTR;
|
49
|
+
|
50
|
+
/* these types were deprecated but still used by old drivers and
|
51
|
+
* applications. So just declare and use them. */
|
52
|
+
typedef LPSTR LPTSTR;
|
53
|
+
typedef LPCSTR LPCTSTR;
|
54
|
+
|
55
|
+
#else
|
56
|
+
#include <windows.h>
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#ifdef __cplusplus
|
60
|
+
}
|
61
|
+
#endif
|
62
|
+
|
63
|
+
#endif
|
data/lib/smartcard.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'smartcard_pcsc'
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'smartcard'
|
2
|
+
|
3
|
+
def test_reader_states
|
4
|
+
reader_states = Smartcard::PCSC::ReaderStates.new(2)
|
5
|
+
reader_states.set_current_state_of!(1, Smartcard::PCSC::STATE_ATRMATCH)
|
6
|
+
reader_states.set_current_state_of!(0, Smartcard::PCSC::STATE_CHANGED)
|
7
|
+
reader_states.set_event_state_of!(0, Smartcard::PCSC::STATE_IGNORE)
|
8
|
+
reader_states.set_event_state_of!(1, Smartcard::PCSC::STATE_PRESENT)
|
9
|
+
reader_states.set_atr_of!(1, "Ruby\0rocks!")
|
10
|
+
reader_states.set_atr_of!(0, "grreat success")
|
11
|
+
reader_states.set_reader_name_of!(0, "PC/SC Reader 0")
|
12
|
+
reader_states.set_reader_name_of!(1, "CCID Reader 1")
|
13
|
+
|
14
|
+
test_state1, test_state0 = reader_states.current_state_of(1), reader_states.current_state_of(0)
|
15
|
+
if (test_state1 != Smartcard::PCSC::STATE_ATRMATCH) or (test_state0 != Smartcard::PCSC::STATE_CHANGED)
|
16
|
+
puts "FAILED: ReaderStates.set_current_state_of! / current_state_of returned #{test_state1},#{test_state0} instead of #{Smartcard::PCSC::STATE_ATRMATCH},#{Smartcard::PCSC::STATE_CHANGED}\n"
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
test_state0, test_state1 = reader_states.event_state_of(0), reader_states.event_state_of(1)
|
20
|
+
if (test_state0 != Smartcard::PCSC::STATE_IGNORE) or (test_state1 != Smartcard::PCSC::STATE_PRESENT)
|
21
|
+
puts "FAILED: ReaderStates.set_event_state_of! / event_state_of returned #{test_state0},#{test_state1} instead of #{Smartcard::PCSC::STATE_IGNORE},#{Smartcard::PCSC::STATE_PRESENT}\n"
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
test_atr1, test_atr0 = reader_states.atr_of(1), reader_states.atr_of(0)
|
25
|
+
if (test_atr1 != "Ruby\0rocks!") or (test_atr0 != "grreat success")
|
26
|
+
puts "FAILED: ReaderStates.set_atr_of! / atr_of returned '#{test_atr1}','#{test_atr0}' instead of 'Ruby\\0rocks!','grreat success'\n"
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
test_reader0, test_reader1 = reader_states.reader_name_of(0), reader_states.reader_name_of(1)
|
30
|
+
if (test_reader0 != "PC/SC Reader 0") or (test_reader1 != "CCID Reader 1")
|
31
|
+
puts "FAILED: ReaderStates.set_reader_name_of! / reader_name_of returned '#{test_reader0}','#{test_reader1}' instead of 'PC/SC Reader 0','CCID Reader 1'\n"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
[5, 2, nil].each do |bad_index|
|
36
|
+
exception_thrown = false
|
37
|
+
begin
|
38
|
+
reader_states.current_state_of(bad_index)
|
39
|
+
rescue IndexError => e
|
40
|
+
puts "(expected) exception thrown: #{e}\n"
|
41
|
+
exception_thrown = e
|
42
|
+
rescue TypeError => e
|
43
|
+
puts "(expected) exception thrown: #{e}\n"
|
44
|
+
exception_thrown = e
|
45
|
+
end
|
46
|
+
unless exception_thrown
|
47
|
+
puts "FAILED: ReaderStates.current_state_of responded for bad index #{bad_index}\n"
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_io_request
|
56
|
+
io_request = Smartcard::PCSC::IoRequest.new
|
57
|
+
[Smartcard::PCSC::PROTOCOL_T0, Smartcard::PCSC::PROTOCOL_T1, Smartcard::PCSC::PROTOCOL_RAW].each do |t_protocol|
|
58
|
+
io_request.protocol = t_protocol
|
59
|
+
r_protocol = io_request.protocol
|
60
|
+
if r_protocol != t_protocol
|
61
|
+
puts "FAILED: IoRequest.protocol= / protocol failed for protocol #{t_protocol} (got #{r_protocol} instead)\n"
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
test_reader_states
|
68
|
+
test_io_request
|
69
|
+
|
70
|
+
|
71
|
+
context = Smartcard::PCSC::Context.new(Smartcard::PCSC::SCOPE_SYSTEM);
|
72
|
+
|
73
|
+
reader_groups = context.list_reader_groups
|
74
|
+
pp reader_groups
|
75
|
+
readers1 = context.list_readers reader_groups
|
76
|
+
pp readers1
|
77
|
+
readers2 = context.list_readers reader_groups.first
|
78
|
+
pp readers2
|
79
|
+
readers3 = context.list_readers nil
|
80
|
+
pp readers3
|
81
|
+
|
82
|
+
context.cancel
|
83
|
+
|
84
|
+
reader0 = readers3.first
|
85
|
+
puts "Waiting for card in reader: #{reader0}\n"
|
86
|
+
reader_states = Smartcard::PCSC::ReaderStates.new(1)
|
87
|
+
reader_states.set_reader_name_of!(0, reader0)
|
88
|
+
reader_states.set_current_state_of!(0, Smartcard::PCSC::STATE_UNKNOWN)
|
89
|
+
while (reader_states.event_state_of(0) & Smartcard::PCSC::STATE_PRESENT) == 0 do
|
90
|
+
context.get_status_change reader_states, Smartcard::PCSC::INFINITE_TIMEOUT
|
91
|
+
puts "Status change: now it's #{reader_states.event_state_of(0)} and we want #{Smartcard::PCSC::STATE_PRESENT}\n"
|
92
|
+
reader_states.acknowledge_events!
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "Connecting to card\n"
|
96
|
+
card0 = Smartcard::PCSC::Card.new(context, reader0, Smartcard::PCSC::SHARE_SHARED, Smartcard::PCSC::PROTOCOL_ANY)
|
97
|
+
|
98
|
+
card0.begin_transaction
|
99
|
+
card0.end_transaction Smartcard::PCSC::DISPOSITION_LEAVE
|
100
|
+
|
101
|
+
card0.reconnect Smartcard::PCSC::SHARE_EXCLUSIVE, Smartcard::PCSC::PROTOCOL_ANY, Smartcard::PCSC::INITIALIZATION_RESET
|
102
|
+
|
103
|
+
card_status = card0.status
|
104
|
+
pp card_status
|
105
|
+
puts "ATR Length: #{card_status[:atr].length}\n"
|
106
|
+
|
107
|
+
begin
|
108
|
+
puts "IFD vendor: #{card0.get_attribute Smartcard::PCSC::ATTR_VENDOR_IFD_VERSION}\n"
|
109
|
+
rescue RuntimeError => e
|
110
|
+
puts "Card.get_attribute threw exception #{e}\n"
|
111
|
+
end
|
112
|
+
|
113
|
+
puts "Selecting applet\n"
|
114
|
+
aid = [0x19, 0x83, 0x12, 0x29, 0xba, 0xbe]
|
115
|
+
select_apdu = [0x00, 0xA4, 0x04, 0x00, aid.length, aid].flatten
|
116
|
+
send_ioreq = Smartcard::PCSC::IoRequest.new; send_ioreq.protocol = Smartcard::PCSC::PROTOCOL_T1;
|
117
|
+
recv_ioreq = Smartcard::PCSC::IoRequest.new
|
118
|
+
select_response = card0.transmit(select_apdu.map {|byte| byte.chr}.join(''), send_ioreq, recv_ioreq)
|
119
|
+
select_response_str = (0...select_response.length).map { |i| ' %02x' % select_response[i].to_i }.join('')
|
120
|
+
puts "Response:#{select_response_str}\n"
|
121
|
+
|
122
|
+
# This only works with GemPlus readers... any other suggestions?
|
123
|
+
puts "Testing low-level control\n"
|
124
|
+
ctl_string = [0x82, 0x01, 0x07, 0x00].map {|byte| byte.chr}.join('')
|
125
|
+
ctl_response = card0.control 2049, ctl_string, 4
|
126
|
+
pp ctl_response
|
127
|
+
|
128
|
+
puts "Disconnecting and cleaning up\n"
|
129
|
+
card0.disconnect Smartcard::PCSC::DISPOSITION_LEAVE
|
130
|
+
context.release
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: smartcard
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-11-16 00:00:00 -05:00
|
8
|
+
summary: Interface with ISO 7816 smart cards.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: victor@costan.us
|
12
|
+
homepage: http://www.costan.us/smartcard
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: smartcard
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Victor Costan
|
31
|
+
files:
|
32
|
+
- lib/smartcard.rb
|
33
|
+
- ext/smartcard_pcsc
|
34
|
+
- ext/smartcard_pcsc/extconf.rb
|
35
|
+
- ext/smartcard_pcsc/pcsc.h
|
36
|
+
- ext/smartcard_pcsc/pcsc_card.c
|
37
|
+
- ext/smartcard_pcsc/pcsc_constants.c
|
38
|
+
- ext/smartcard_pcsc/pcsc_context.c
|
39
|
+
- ext/smartcard_pcsc/pcsc_io_request.c
|
40
|
+
- ext/smartcard_pcsc/pcsc_main.c
|
41
|
+
- ext/smartcard_pcsc/pcsc_multi_strings.c
|
42
|
+
- ext/smartcard_pcsc/pcsc_namespace.c
|
43
|
+
- ext/smartcard_pcsc/pcsc_reader_states.c
|
44
|
+
- ext/smartcard_pcsc/pcsc_surrogate_reader.h
|
45
|
+
- ext/smartcard_pcsc/pcsc_surrogate_wintypes.h
|
46
|
+
- tests/ts_pcsc_ext.rb
|
47
|
+
test_files: []
|
48
|
+
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
extra_rdoc_files: []
|
52
|
+
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions:
|
56
|
+
- ext/smartcard_pcsc/extconf.rb
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
dependencies: []
|
60
|
+
|