Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include <vector>

// The rule of five (C++ Core guidelines C.21).
#define PCSC_CPP_DEFAULT_MOVE(Class) \
Class(Class&&) = default; \
Class& operator=(Class&&) = default
#define PCSC_CPP_DISABLE_COPY(Class) \
Class(const Class&) = delete; \
Class& operator=(const Class&) = delete
Expand Down Expand Up @@ -162,6 +165,8 @@ struct CommandApdu
d.push_back(le);
}

virtual ~CommandApdu() noexcept = default;

constexpr operator const byte_vector&() const { return d; }

/**
Expand Down Expand Up @@ -213,6 +218,37 @@ struct CommandApdu
return {0x00, 0xb0, byte_type(pos >> 8), byte_type(pos), le};
}

/**
* A helper function to create a VERIFY command APDU.
* The ISO 7816-4 Section 6.12 VERIFY command has the form:
* CLA = 0x00
* INS = 0x20
* P1 = Only P1=’00’ is valid (other values are RFU)
* P2 = Qualifier of the reference data
* Lc and Data field = Empty or verification data
* Le = Empty
*/
static PCSC_CPP_CONSTEXPR_VECTOR CommandApdu verify(byte_type p2, byte_vector&& pin,
size_t paddingLength,
pcsc_cpp::byte_type paddingChar)
{
if (!pin.empty() && pin.capacity() < paddingLength + 5) {
throw std::invalid_argument(
"PIN buffer does not have enough capacity to pad without reallocation");
}
if (pin.size() < paddingLength) {
pin.insert(pin.end(), paddingLength - pin.size(), paddingChar);
}
struct VerifyApdu final : public CommandApdu
{
using CommandApdu::CommandApdu;
PCSC_CPP_DISABLE_COPY(VerifyApdu);
PCSC_CPP_DEFAULT_MOVE(VerifyApdu);
constexpr ~VerifyApdu() noexcept final { std::fill(d.begin(), d.end(), byte_type(0)); }
};
return VerifyApdu {0x00, 0x20, 0x00, p2, std::move(pin)};
}

byte_vector d;
};

Expand Down
24 changes: 5 additions & 19 deletions src/electronic-ids/pcsc/pcsc-common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,33 +87,19 @@ inline pcsc_cpp::byte_vector readFile(const pcsc_cpp::SmartCard::Session& sessio
return readBinary(session, pcsc_cpp::toSW(*size.begin, *(size.begin + 1)), blockLength);
}

PCSC_CPP_CONSTEXPR_VECTOR inline pcsc_cpp::byte_vector
addPaddingToPin(pcsc_cpp::byte_vector&& pin, size_t paddingLength, pcsc_cpp::byte_type paddingChar)
{
if (pin.capacity() < paddingLength) {
THROW(ProgrammingError,
"PIN buffer does not have enough capacity to pad without reallocation");
}
if (pin.size() < paddingLength) {
pin.insert(pin.end(), paddingLength - pin.size(), paddingChar);
}
return std::move(pin);
}

inline void verifyPin(const pcsc_cpp::SmartCard::Session& session, pcsc_cpp::byte_type p2,
pcsc_cpp::byte_vector&& pin, ElectronicID::PinMinMaxLength pinMinMax,
pcsc_cpp::byte_type paddingChar)
{
pcsc_cpp::ResponseApdu response;

if (session.readerHasPinPad()) {
const pcsc_cpp::CommandApdu verifyPin {
0x00, 0x20, 0x00, p2, pcsc_cpp::byte_vector(pinMinMax.second, paddingChar)};
response = session.transmitCTL(verifyPin, 0, pinMinMax.first);
response = session.transmitCTL(
pcsc_cpp::CommandApdu::verify(p2, std::move(pin), pinMinMax.second, paddingChar), 0,
pinMinMax.first);
} else {
const pcsc_cpp::CommandApdu verifyPin {
0x00, 0x20, 0x00, p2, addPaddingToPin(std::move(pin), pinMinMax.second, paddingChar)};
response = session.transmit(verifyPin);
response = session.transmit(
pcsc_cpp::CommandApdu::verify(p2, std::move(pin), pinMinMax.second, paddingChar));
}

// NOTE: in case card-specific error handling logic is needed,
Expand Down
16 changes: 8 additions & 8 deletions tests/mock/test-get-certificate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ TEST(electronic_id_test, selectCertificateEstIDEMIA)
const HashAlgorithm hashAlgo = authAlgo.hashAlgorithm();

pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
authPin.reserve(12);
authPin.reserve(17);

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

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

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

pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
authPin.reserve(12);
authPin.reserve(17);

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

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

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

pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
authPin.reserve(12);
authPin.reserve(17);

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

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

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

pcsc_cpp::byte_vector authPin {'1', '2', '3', '4'};
authPin.reserve(12);
authPin.reserve(17);

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

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

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