Skip to content

Commit 2dc845a

Browse files
committed
Use CommandAPDU instead byte_vector
Signed-off-by: Raul Metsma <[email protected]>
1 parent 7f91f6a commit 2dc845a

File tree

2 files changed

+45
-47
lines changed

2 files changed

+45
-47
lines changed

lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,15 @@ struct CommandApdu
165165
d.push_back(le);
166166
}
167167

168-
virtual ~CommandApdu() noexcept = default;
168+
PCSC_CPP_CONSTEXPR_VECTOR CommandApdu(const CommandApdu &other, byte_type le) :
169+
d(other.d)
170+
{
171+
size_t pos = d.size() <= 5 ? 4 : 5 + d[4]; // Case 1/2 or 3/4
172+
d.resize(pos + 1);
173+
d[pos] = le;
174+
}
169175

170-
constexpr operator const byte_vector&() const { return d; }
176+
virtual ~CommandApdu() = default;
171177

172178
/**
173179
* A helper function to create a SELECT FILE command APDU.
@@ -249,6 +255,21 @@ struct CommandApdu
249255
return VerifyApdu {0x00, 0x20, 0x00, p2, std::move(pin)};
250256
}
251257

258+
/**
259+
* A helper function to create a GET RESPONSE command APDU.
260+
*
261+
* The ISO 7816-4 Section 7.1 GET RESPONSE command has the form:
262+
* CLA = 0x00
263+
* INS = 0xC0
264+
* P1, P2 = ‘0000’ (other values are RFU)
265+
* Lc and Data field = Empty
266+
* Le = Maximum length of data expected in response
267+
*/
268+
static PCSC_CPP_CONSTEXPR_VECTOR CommandApdu getResponse(byte_type le = 0x00)
269+
{
270+
return {0x00, 0xc0, 0x00, 0x00, le};
271+
}
272+
252273
byte_vector d;
253274
};
254275

lib/libpcsc-cpp/src/SmartCard.cpp

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -142,29 +142,16 @@ class CardImpl
142142
|| features.contains(FEATURE_VERIFY_PIN_DIRECT);
143143
}
144144

145-
ResponseApdu transmitBytes(const byte_vector& commandBytes) const
145+
ResponseApdu transmitBytes(const CommandApdu& commandApdu) const
146146
{
147147
byte_vector responseBytes(ResponseApdu::MAX_SIZE, 0);
148148
auto responseLength = DWORD(responseBytes.size());
149-
150-
// TODO: debug("Sending: " + bytes2hexstr(commandBytes))
151-
152-
SCard(Transmit, cardHandle, &_protocol, commandBytes.data(), DWORD(commandBytes.size()),
149+
SCard(Transmit, cardHandle, &_protocol, commandApdu.d.data(), DWORD(commandApdu.d.size()),
153150
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;
151+
return toResponse(std::move(responseBytes), responseLength);
165152
}
166153

167-
ResponseApdu transmitBytesCTL(const byte_vector& commandBytes, uint16_t lang,
154+
ResponseApdu transmitBytesCTL(const CommandApdu& commandApdu, uint16_t lang,
168155
uint8_t minlen) const
169156
{
170157
uint8_t PINFrameOffset = 0;
@@ -182,8 +169,8 @@ class CardImpl
182169
data->bNumberMessage = CCIDDefaultInvitationMessage;
183170
data->wLangId = lang;
184171
data->bMsgIndex = NoInvitationMessage;
185-
data->ulDataLength = uint32_t(commandBytes.size());
186-
cmd.insert(cmd.cend(), commandBytes.cbegin(), commandBytes.cend());
172+
data->ulDataLength = uint32_t(commandApdu.d.size());
173+
cmd.insert(cmd.cend(), commandApdu.d.cbegin(), commandApdu.d.cend());
187174

188175
DWORD ioctl =
189176
features.at(features.contains(FEATURE_VERIFY_PIN_START) ? FEATURE_VERIFY_PIN_START
@@ -266,31 +253,6 @@ class CardImpl
266253
+ std::to_string(_protocol.dwProtocol));
267254
}
268255
}
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-
}
294256
};
295257

296258
SmartCard::Session::Session(const CardImpl& card) : card(card)
@@ -309,7 +271,22 @@ SmartCard::Session::~Session() noexcept
309271

310272
ResponseApdu SmartCard::Session::transmit(const CommandApdu& command) const
311273
{
312-
return card.transmitBytes(command);
274+
auto response = card.transmitBytes(command);
275+
if (response.sw1 == ResponseApdu::WRONG_LE_LENGTH) {
276+
response = card.transmitBytes(CommandApdu(command, response.sw2));
277+
}
278+
if (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
279+
auto getResponseCommand = CommandApdu::getResponse();
280+
while (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) {
281+
getResponseCommand.d[4] = response.sw2;
282+
auto newResponse = card.transmitBytes(getResponseCommand);
283+
response.sw1 = newResponse.sw1;
284+
response.sw2 = newResponse.sw2;
285+
response.data.insert(response.data.end(), newResponse.data.cbegin(),
286+
newResponse.data.cend());
287+
}
288+
}
289+
return response;
313290
}
314291

315292
ResponseApdu SmartCard::Session::transmitCTL(const CommandApdu& command, uint16_t lang,

0 commit comments

Comments
 (0)