Skip to content

Commit 0787620

Browse files
committed
Read binary
Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent f47fc15 commit 0787620

File tree

3 files changed

+32
-48
lines changed

3 files changed

+32
-48
lines changed

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ struct CommandApdu
181181
constexpr operator const byte_vector&() const { return d; }
182182

183183
/**
184-
* A helper function to create a SELECT command APDU.
184+
* A helper function to create a SELECT FILE command APDU.
185185
*
186-
* The ISO 7816-4 Section 6.11 SELECT command has the form:
186+
* The ISO 7816-4 Section 6.11 SELECT FILE command has the form:
187187
* CLA = 0x00
188188
* INS = 0xA4
189189
* P1 = varies, see below.
@@ -202,6 +202,20 @@ struct CommandApdu
202202
return {0x00, 0xA4, p1, 0x0C, std::move(file)};
203203
}
204204

205+
/**
206+
* A helper function to create a READ BINARY command APDU.
207+
*
208+
* The ISO 7816-4 Section 6.11 READ BINARY command has the form:
209+
* CLA = 0x00
210+
* INS = 0xB0
211+
* P1, P2 = then P1||P2 is the offset of the first byte to be read in data units from the
212+
* beginning of the file. Lc and Data field = Empty Le = Number of bytes to be read
213+
*/
214+
static PCSC_CPP_CONSTEXPR_VECTOR CommandApdu readBinary(uint16_t pos, byte_type le)
215+
{
216+
return {0x00, 0xb0, byte_type(pos >> 8), byte_type(pos), le};
217+
}
218+
205219
byte_vector d;
206220
};
207221

@@ -301,10 +315,10 @@ std::vector<Reader> listReaders();
301315
void transmitApduWithExpectedResponse(const SmartCard& card, const CommandApdu& command);
302316

303317
/** Read data length from currently selected file header, file must be ASN.1-encoded. */
304-
size_t readDataLengthFromAsn1(const SmartCard& card);
318+
uint16_t readDataLengthFromAsn1(const SmartCard& card);
305319

306320
/** Read lenght bytes from currently selected binary file in blockLength-sized chunks. */
307-
byte_vector readBinary(const SmartCard& card, const size_t length, byte_type blockLength);
321+
byte_vector readBinary(const SmartCard& card, const uint16_t length, byte_type blockLength = 0xFF);
308322

309323
// Errors.
310324

lib/libpcsc-cpp/src/utils.cpp

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,13 @@
2323
#include "pcsc-cpp/pcsc-cpp.hpp"
2424
#include "pcsc-cpp/pcsc-cpp-utils.hpp"
2525

26-
#include <sstream>
26+
#include <algorithm>
2727
#include <iomanip>
28+
#include <sstream>
2829

2930
using namespace pcsc_cpp;
3031
using namespace std::string_literals;
3132

32-
#ifdef HIBYTE
33-
#undef HIBYTE
34-
#endif
35-
#ifdef LOBYTE
36-
#undef LOBYTE
37-
#endif
38-
39-
constexpr byte_type HIBYTE(size_t w) noexcept
40-
{
41-
return static_cast<byte_type>((w >> 8) & 0xff);
42-
}
43-
constexpr byte_type LOBYTE(size_t w) noexcept
44-
{
45-
return static_cast<byte_type>(w & 0xff);
46-
}
47-
4833
namespace
4934
{
5035

@@ -93,14 +78,9 @@ void transmitApduWithExpectedResponse(const SmartCard& card, const CommandApdu&
9378
}
9479
}
9580

96-
size_t readDataLengthFromAsn1(const SmartCard& card)
81+
uint16_t readDataLengthFromAsn1(const SmartCard& card)
9782
{
98-
// p1 - offset size first byte, 0
99-
// p2 - offset size second byte, 0
100-
// le - number of bytes to read, need 4 bytes from start for length
101-
const CommandApdu readBinary4Bytes {0x00, 0xb0, 0x00, 0x00, 0x04};
102-
103-
auto response = card.transmit(readBinary4Bytes);
83+
auto response = card.transmit(CommandApdu::readBinary(0, 0x04));
10484

10585
// Verify expected DER header, first byte must be SEQUENCE.
10686
if (response.data[0] != DER_SEQUENCE_TYPE_TAG) {
@@ -121,7 +101,7 @@ size_t readDataLengthFromAsn1(const SmartCard& card)
121101
}
122102

123103
// Read 2-byte length field at offset 2 and 3 and add the 4 DER length bytes.
124-
const auto length = size_t((response.data[2] << 8) + response.data[3] + 4);
104+
const uint16_t length = toSW(response.data[2], response.data[3]) + 4;
125105
if (length < 128 || length > 0x0f00) {
126106
// TODO: more specific exception
127107
THROW(Error,
@@ -132,29 +112,19 @@ size_t readDataLengthFromAsn1(const SmartCard& card)
132112
return length;
133113
}
134114

135-
byte_vector readBinary(const SmartCard& card, const size_t length, byte_type blockLength)
115+
byte_vector readBinary(const SmartCard& card, const uint16_t length, byte_type blockLength)
136116
{
137-
auto lengthCounter = length;
138117
auto resultBytes = byte_vector {};
139-
140-
for (size_t offset = 0; lengthCounter != 0;
141-
offset += blockLength, lengthCounter -= blockLength) {
142-
143-
if (blockLength > lengthCounter) {
144-
blockLength = byte_type(lengthCounter);
118+
while (resultBytes.size() < length) {
119+
blockLength = byte_type(std::min<size_t>(length - resultBytes.size(), blockLength));
120+
auto response = card.transmit(CommandApdu::readBinary(uint16_t(resultBytes.size()), blockLength));
121+
if (response.data.size() != blockLength) {
122+
THROW(Error,
123+
"readBinary(): Invalid length received: "s + std::to_string(response.data.size())
124+
+ " excpected: " + std::to_string(blockLength));
145125
}
146-
147-
CommandApdu readBinary {0x00, 0xb0, HIBYTE(offset), LOBYTE(offset), blockLength};
148-
auto response = card.transmit(readBinary);
149-
150126
resultBytes.insert(resultBytes.end(), response.data.cbegin(), response.data.cend());
151127
}
152-
153-
if (resultBytes.size() != length) {
154-
// TODO: more specific exception
155-
THROW(Error, "readBinary(): Invalid length: "s + std::to_string(resultBytes.size()));
156-
}
157-
158128
return resultBytes;
159129
}
160130

src/electronic-ids/pcsc/LatEIDIDEMIAv2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ inline byte_vector readEF_File(const SmartCard& card, const byte_vector& file)
6060
THROW(SmartCardError, "Failed to read EF file length");
6161
}
6262
pos += byte_vector::difference_type(findLength.size());
63-
return readBinary(card, size_t(*pos << 8) + *(pos + 1), 0xFF);
63+
return readBinary(card, toSW(*pos, *(pos + 1)));
6464
}
6565

6666
inline byte_vector readEF_PrKD(const SmartCard& card)

0 commit comments

Comments
 (0)