Skip to content

Commit eddf6b9

Browse files
committed
Clear PIN from buffer on destruction
WE2-1055 Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent affadb3 commit eddf6b9

File tree

3 files changed

+61
-27
lines changed

3 files changed

+61
-27
lines changed

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ struct ResponseApdu
127127
*/
128128
struct CommandApdu
129129
{
130+
static constexpr size_t APDU_HEADER_AND_LC_SIZE = 5;
130131
static constexpr size_t MAX_DATA_SIZE = 255;
131132

132133
// ISO 7816 part 4, Annex B.1, Case 1
@@ -162,6 +163,12 @@ struct CommandApdu
162163
d.push_back(le);
163164
}
164165

166+
PCSC_CPP_CONSTEXPR_VECTOR void clear() && noexcept
167+
{
168+
std::fill(d.begin(), d.end(), byte_type(0));
169+
d.clear();
170+
}
171+
165172
constexpr operator const byte_vector&() const { return d; }
166173

167174
/**
@@ -213,6 +220,44 @@ struct CommandApdu
213220
return {0x00, 0xb0, byte_type(pos >> 8), byte_type(pos), le};
214221
}
215222

223+
/**
224+
* A helper function to create a VERIFY command APDU.
225+
* The ISO 7816-4 Section 6.12 VERIFY command has the form:
226+
* CLA = 0x00
227+
* INS = 0x20
228+
* P1 = Only P1=’00’ is valid (other values are RFU)
229+
* P2 = Qualifier of the reference data
230+
* Lc and Data field = Empty or verification data
231+
* Le = Empty
232+
*/
233+
static PCSC_CPP_CONSTEXPR_VECTOR CommandApdu verify(byte_type p2, byte_vector&& pin,
234+
size_t paddingLength,
235+
pcsc_cpp::byte_type paddingChar)
236+
{
237+
if (!pin.empty() && pin.capacity() < paddingLength + APDU_HEADER_AND_LC_SIZE) {
238+
throw std::invalid_argument(
239+
"PIN buffer does not have enough capacity to pad without reallocation");
240+
}
241+
if (pin.size() > paddingLength) {
242+
throw std::invalid_argument("PIN length exceeds maximum length");
243+
}
244+
if (pin.size() < paddingLength) {
245+
pin.insert(pin.end(), paddingLength - pin.size(), paddingChar);
246+
}
247+
return {0x00, 0x20, 0x00, p2, std::move(pin)};
248+
}
249+
250+
/**
251+
* A helper function to create a VERIFY command APDU with empty data field and only padding.
252+
*/
253+
static PCSC_CPP_CONSTEXPR_VECTOR CommandApdu verify(byte_type p2, size_t paddingLength,
254+
pcsc_cpp::byte_type paddingChar)
255+
{
256+
byte_vector emptyPin;
257+
emptyPin.reserve(paddingLength + APDU_HEADER_AND_LC_SIZE);
258+
return verify(p2, std::move(emptyPin), paddingLength, paddingChar);
259+
}
260+
216261
byte_vector d;
217262
};
218263

src/electronic-ids/pcsc/pcsc-common.hpp

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "electronic-id/electronic-id.hpp"
2626
#include "../TLV.hpp"
27+
#include "../scope.hpp"
2728

2829
#include "pcsc-cpp/pcsc-cpp-utils.hpp"
2930

@@ -87,33 +88,21 @@ inline pcsc_cpp::byte_vector readFile(const pcsc_cpp::SmartCard::Session& sessio
8788
return readBinary(session, pcsc_cpp::toSW(*size.begin, *(size.begin + 1)), blockLength);
8889
}
8990

90-
PCSC_CPP_CONSTEXPR_VECTOR inline pcsc_cpp::byte_vector
91-
addPaddingToPin(pcsc_cpp::byte_vector&& pin, size_t paddingLength, pcsc_cpp::byte_type paddingChar)
92-
{
93-
if (pin.capacity() < paddingLength) {
94-
THROW(ProgrammingError,
95-
"PIN buffer does not have enough capacity to pad without reallocation");
96-
}
97-
if (pin.size() < paddingLength) {
98-
pin.insert(pin.end(), paddingLength - pin.size(), paddingChar);
99-
}
100-
return std::move(pin);
101-
}
102-
10391
inline void verifyPin(const pcsc_cpp::SmartCard::Session& session, pcsc_cpp::byte_type p2,
10492
pcsc_cpp::byte_vector&& pin, ElectronicID::PinMinMaxLength pinMinMax,
10593
pcsc_cpp::byte_type paddingChar)
10694
{
10795
pcsc_cpp::ResponseApdu response;
10896

10997
if (session.readerHasPinPad()) {
110-
const pcsc_cpp::CommandApdu verifyPin {
111-
0x00, 0x20, 0x00, p2, pcsc_cpp::byte_vector(pinMinMax.second, paddingChar)};
112-
response = session.transmitCTL(verifyPin, 0, pinMinMax.first);
98+
response = session.transmitCTL(
99+
pcsc_cpp::CommandApdu::verify(p2, pinMinMax.second, paddingChar), 0, pinMinMax.first);
113100
} else {
114-
const pcsc_cpp::CommandApdu verifyPin {
115-
0x00, 0x20, 0x00, p2, addPaddingToPin(std::move(pin), pinMinMax.second, paddingChar)};
116-
response = session.transmit(verifyPin);
101+
auto verifyCommand =
102+
pcsc_cpp::CommandApdu::verify(p2, std::move(pin), pinMinMax.second, paddingChar);
103+
auto clearPinCommand = stdext::make_scope_exit(
104+
[&verifyCommand]() noexcept { std::move(verifyCommand).clear(); });
105+
response = session.transmit(verifyCommand);
117106
}
118107

119108
// NOTE: in case card-specific error handling logic is needed,

tests/mock/test-get-certificate.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ TEST(electronic_id_test, selectCertificateEstIDEMIA)
5555
const HashAlgorithm hashAlgo = authAlgo.hashAlgorithm();
5656

5757
pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
58-
authPin.reserve(12);
58+
authPin.reserve(17);
5959

6060
const auto hash = calculateDigest(hashAlgo, dataToSign);
6161
const auto authSignature = cardInfo->signWithAuthKey(std::move(authPin), hash);
@@ -72,7 +72,7 @@ TEST(electronic_id_test, selectCertificateEstIDEMIA)
7272
EXPECT_EQ(signingRetriesLeft.maxRetry, 3);
7373

7474
pcsc_cpp::byte_vector signPin {'1', '2', '3', '4', '5'};
75-
signPin.reserve(12);
75+
signPin.reserve(17);
7676

7777
EXPECT_EQ(cardInfo->isSupportedSigningHashAlgorithm(hashAlgo), true);
7878
const auto signSignature = cardInfo->signWithSigningKey(std::move(signPin), hash, hashAlgo);
@@ -105,7 +105,7 @@ TEST(electronic_id_test, selectCertificateFinV3)
105105
const HashAlgorithm hashAlgo = authAlgo.hashAlgorithm();
106106

107107
pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
108-
authPin.reserve(12);
108+
authPin.reserve(17);
109109

110110
const auto hash = calculateDigest(hashAlgo, dataToSign);
111111
const auto authSignature = cardInfo->signWithAuthKey(std::move(authPin), hash);
@@ -122,7 +122,7 @@ TEST(electronic_id_test, selectCertificateFinV3)
122122
EXPECT_EQ(signingRetriesLeft.maxRetry, 5);
123123

124124
pcsc_cpp::byte_vector signPin {'1', '2', '3', '4', '5', '6'};
125-
signPin.reserve(12);
125+
signPin.reserve(17);
126126

127127
EXPECT_EQ(cardInfo->isSupportedSigningHashAlgorithm(hashAlgo), true);
128128
const auto signSignature = cardInfo->signWithSigningKey(std::move(signPin), hash, hashAlgo);
@@ -155,7 +155,7 @@ TEST(electronic_id_test, selectCertificateFinV4)
155155
const HashAlgorithm hashAlgo = authAlgo.hashAlgorithm();
156156

157157
pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
158-
authPin.reserve(12);
158+
authPin.reserve(17);
159159

160160
const auto hash = calculateDigest(hashAlgo, dataToSign);
161161
const auto authSignature = cardInfo->signWithAuthKey(std::move(authPin), hash);
@@ -172,7 +172,7 @@ TEST(electronic_id_test, selectCertificateFinV4)
172172
EXPECT_EQ(signingRetriesLeft.maxRetry, 5);
173173

174174
pcsc_cpp::byte_vector signPin {'1', '2', '3', '4', '5', '6'};
175-
signPin.reserve(12);
175+
signPin.reserve(17);
176176

177177
EXPECT_EQ(cardInfo->isSupportedSigningHashAlgorithm(hashAlgo), true);
178178
const auto signSignature = cardInfo->signWithSigningKey(std::move(signPin), hash, hashAlgo);
@@ -205,7 +205,7 @@ TEST(electronic_id_test, selectCertificateLatV2)
205205
const HashAlgorithm hashAlgo = authAlgo.hashAlgorithm();
206206

207207
pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
208-
authPin.reserve(12);
208+
authPin.reserve(17);
209209

210210
const auto hash = calculateDigest(hashAlgo, dataToSign);
211211
const auto authSignature = cardInfo->signWithAuthKey(std::move(authPin), hash);
@@ -222,7 +222,7 @@ TEST(electronic_id_test, selectCertificateLatV2)
222222
EXPECT_EQ(signingRetriesLeft.maxRetry, 3);
223223

224224
pcsc_cpp::byte_vector signPin {'1', '2', '3', '4', '5', '6'};
225-
signPin.reserve(12);
225+
signPin.reserve(17);
226226

227227
EXPECT_EQ(cardInfo->isSupportedSigningHashAlgorithm(hashAlgo), true);
228228
const auto signSignature = cardInfo->signWithSigningKey(std::move(signPin), hash, hashAlgo);

0 commit comments

Comments
 (0)