4141namespace
4242{
4343
44- template <class K , class V = uint32_t , class D , size_t dsize, typename Func>
45- constexpr std::map<K, V> parseTLV (const std::array<D, dsize>& data, DWORD size, Func transform)
46- {
47- std::map<K, V> result;
48- for (auto p = data.cbegin (); DWORD (std::distance (data.cbegin (), p)) < size;) {
49- auto tag = K (*p++);
50- V value {};
51- for (unsigned int i = 0 , len = *p++; i < len; ++i)
52- value |= V (*p++) << 8 * i;
53- result[tag] = transform (value);
54- }
55- return result;
56- }
57-
5844constexpr uint32_t VENDOR_HID_GLOBAL = 0x076B ;
5945constexpr uint32_t OMNIKEY_3x21 = 0x3031 ;
6046constexpr uint32_t OMNIKEY_6121 = 0x6632 ;
@@ -103,13 +89,16 @@ class CardImpl
10389 std::array<BYTE, 256 > buf {};
10490 SCard (Control, cardHandle, ioctl->second , nullptr , 0U , buf.data (),
10591 DWORD (buf.size ()), &size);
106- auto properties = parseTLV<TLV_PROPERTIES>(buf, size, [](uint32_t t) { return t; });
107- if (auto vendor = properties.find (TLV_PROPERTY_wIdVendor);
108- vendor != properties.cend ())
109- id_vendor = vendor->second ;
110- if (auto product = properties.find (TLV_PROPERTY_wIdProduct);
111- product != properties.cend ())
112- id_product = product->second ;
92+ for (auto p = buf.cbegin (); DWORD (std::distance (buf.cbegin (), p)) < size;) {
93+ auto tag = TLV_PROPERTIES (*p++);
94+ uint32_t value {};
95+ for (unsigned int i = 0 , len = *p++; i < len; ++i)
96+ value |= uint32_t (*p++) << 8 * i;
97+ if (tag == TLV_PROPERTY_wIdVendor)
98+ id_vendor = value;
99+ if (tag == TLV_PROPERTY_wIdProduct)
100+ id_product = value;
101+ }
113102 }
114103 } catch (const ScardError&) {
115104 // Ignore driver errors during card feature requests.
@@ -142,29 +131,16 @@ class CardImpl
142131 || features.contains (FEATURE_VERIFY_PIN_DIRECT);
143132 }
144133
145- ResponseApdu transmitBytes (const byte_vector& commandBytes ) const
134+ ResponseApdu transmitBytes (const CommandApdu& commandApdu ) const
146135 {
147136 byte_vector responseBytes (ResponseApdu::MAX_SIZE, 0 );
148137 auto responseLength = DWORD (responseBytes.size ());
149-
150- // TODO: debug("Sending: " + bytes2hexstr(commandBytes))
151-
152- SCard (Transmit, cardHandle, &_protocol, commandBytes.data (), DWORD (commandBytes.size ()),
138+ SCard (Transmit, cardHandle, &_protocol, commandApdu.d .data (), DWORD (commandApdu.d .size ()),
153139 nullptr , responseBytes.data (), &responseLength);
154-
155- auto response = toResponse (std::move (responseBytes), responseLength);
156-
157- if (response.sw1 == ResponseApdu::WRONG_LE_LENGTH) {
158- getResponseWithLE (response, commandBytes);
159- }
160- if (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
161- getMoreResponseData (response);
162- }
163-
164- return response;
140+ return toResponse (std::move (responseBytes), responseLength);
165141 }
166142
167- ResponseApdu transmitBytesCTL (const byte_vector& commandBytes , uint16_t lang,
143+ ResponseApdu transmitBytesCTL (const CommandApdu& commandApdu , uint16_t lang,
168144 uint8_t minlen) const
169145 {
170146 uint8_t PINFrameOffset = 0 ;
@@ -182,8 +158,8 @@ class CardImpl
182158 data->bNumberMessage = CCIDDefaultInvitationMessage;
183159 data->wLangId = lang;
184160 data->bMsgIndex = NoInvitationMessage;
185- data->ulDataLength = uint32_t (commandBytes .size ());
186- cmd.insert (cmd.cend (), commandBytes. cbegin (), commandBytes .cend ());
161+ data->ulDataLength = uint32_t (commandApdu. d .size ());
162+ cmd.insert (cmd.cend (), commandApdu. d . cbegin (), commandApdu. d .cend ());
187163
188164 DWORD ioctl =
189165 features.at (features.contains (FEATURE_VERIFY_PIN_START) ? FEATURE_VERIFY_PIN_START
@@ -266,31 +242,6 @@ class CardImpl
266242 + std::to_string (_protocol.dwProtocol ));
267243 }
268244 }
269-
270- void getMoreResponseData (ResponseApdu& response) const
271- {
272- byte_vector getResponseCommand {0x00 , 0xc0 , 0x00 , 0x00 , 0x00 };
273-
274- ResponseApdu newResponse {response.sw1 , response.sw2 };
275-
276- while (newResponse.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
277- getResponseCommand[4 ] = newResponse.sw2 ;
278- newResponse = transmitBytes (getResponseCommand);
279- response.data .insert (response.data .end (), newResponse.data .cbegin (),
280- newResponse.data .cend ());
281- }
282-
283- response.sw1 = ResponseApdu::OK;
284- response.sw2 = 0 ;
285- }
286-
287- void getResponseWithLE (ResponseApdu& response, byte_vector command) const
288- {
289- size_t pos = command.size () <= 5 ? 4 : 5 + command[4 ]; // Case 1/2 or 3/4
290- command.resize (pos + 1 );
291- command[pos] = response.sw2 ;
292- response = transmitBytes (command);
293- }
294245};
295246
296247SmartCard::Session::Session (const CardImpl& card) : card(card)
@@ -309,7 +260,22 @@ SmartCard::Session::~Session() noexcept
309260
310261ResponseApdu SmartCard::Session::transmit (const CommandApdu& command) const
311262{
312- return card.transmitBytes (command);
263+ auto response = card.transmitBytes (command);
264+ if (response.sw1 == ResponseApdu::WRONG_LE_LENGTH) {
265+ response = card.transmitBytes (CommandApdu (command, response.sw2 ));
266+ }
267+ if (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
268+ auto getResponseCommand = CommandApdu::getResponse ();
269+ while (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
270+ getResponseCommand.d [4 ] = response.sw2 ;
271+ auto newResponse = card.transmitBytes (getResponseCommand);
272+ response.sw1 = newResponse.sw1 ;
273+ response.sw2 = newResponse.sw2 ;
274+ response.data .insert (response.data .end (), newResponse.data .cbegin (),
275+ newResponse.data .cend ());
276+ }
277+ }
278+ return response;
313279}
314280
315281ResponseApdu SmartCard::Session::transmitCTL (const CommandApdu& command, uint16_t lang,
0 commit comments