diff --git a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp index 4d8dd5e..a025352 100644 --- a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp +++ b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp @@ -30,6 +30,9 @@ #include // 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 @@ -162,6 +165,8 @@ struct CommandApdu d.push_back(le); } + virtual ~CommandApdu() noexcept = default; + constexpr operator const byte_vector&() const { return d; } /** @@ -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; }; diff --git a/src/electronic-ids/pcsc/pcsc-common.hpp b/src/electronic-ids/pcsc/pcsc-common.hpp index 2524db1..3dcae6b 100644 --- a/src/electronic-ids/pcsc/pcsc-common.hpp +++ b/src/electronic-ids/pcsc/pcsc-common.hpp @@ -87,19 +87,6 @@ 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) @@ -107,13 +94,12 @@ inline void verifyPin(const pcsc_cpp::SmartCard::Session& session, pcsc_cpp::byt 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, diff --git a/tests/mock/test-get-certificate.cpp b/tests/mock/test-get-certificate.cpp index 4467dec..1359f10 100644 --- a/tests/mock/test-get-certificate.cpp +++ b/tests/mock/test-get-certificate.cpp @@ -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); @@ -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); @@ -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); @@ -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); @@ -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); @@ -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); @@ -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); @@ -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);