From 3a4bbfaa24c25a17c35b54a629553fc27795bdde Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 8 May 2026 15:27:01 +0300 Subject: [PATCH 1/2] Simplify getElectronicID call Signed-off-by: Raul Metsma --- include/electronic-id/electronic-id.hpp | 14 ++++------- src/availableSupportedCards.cpp | 4 ++-- src/electronic-id.cpp | 31 ++++++------------------- tests/mock/test-find-masked-atr.cpp | 28 +++++++++++----------- tests/mock/test-is-card-supported.cpp | 19 ++++++--------- 5 files changed, 35 insertions(+), 61 deletions(-) diff --git a/include/electronic-id/electronic-id.hpp b/include/electronic-id/electronic-id.hpp index c8bafc94..5e6eb432 100644 --- a/include/electronic-id/electronic-id.hpp +++ b/include/electronic-id/electronic-id.hpp @@ -24,8 +24,6 @@ #include "enums.hpp" -#include -#include #include namespace electronic_id @@ -100,7 +98,7 @@ class ElectronicID * By default, this function does nothing. It serves as an extension point for * Pkcs11ElectronicID which needs to release the PKCS#11 module before the application exits to * prevent potential crashes. */ - virtual void release() const {} + virtual void release() const { } virtual std::string name() const = 0; virtual Type type() const = 0; @@ -108,17 +106,13 @@ class ElectronicID virtual pcsc_cpp::SmartCard const& smartcard() const { return card; } protected: - ElectronicID(pcsc_cpp::SmartCard&& _card) noexcept : card(std::move(_card)) {} + ElectronicID(pcsc_cpp::SmartCard&& _card) noexcept : card(std::move(_card)) { } pcsc_cpp::SmartCard card; }; -using ElectronicIDConstructor = std::function; - -std::optional findMaskedATR(const pcsc_cpp::byte_vector& atr); - -bool isCardSupported(const pcsc_cpp::byte_vector& atr); - +/** Returns an electronic ID instance for a supported card in the reader, or nullptr if the card is + * not supported. */ ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader); /** Automatic card selection that either returns a vector of electronic ID pointers with available diff --git a/src/availableSupportedCards.cpp b/src/availableSupportedCards.cpp index bf11dd49..fc641d68 100644 --- a/src/availableSupportedCards.cpp +++ b/src/availableSupportedCards.cpp @@ -44,8 +44,8 @@ std::vector availableSupportedCards() continue; } seenCard = true; - if (isCardSupported(reader.cardAtr)) { - cards.push_back(getElectronicID(reader)); + if (auto eid = getElectronicID(reader)) { + cards.push_back(std::move(eid)); } } diff --git a/src/electronic-id.cpp b/src/electronic-id.cpp index 028b8189..d6d435f3 100644 --- a/src/electronic-id.cpp +++ b/src/electronic-id.cpp @@ -29,6 +29,7 @@ #include "magic_enum/magic_enum.hpp" +#include #include #include @@ -39,6 +40,8 @@ using namespace std::string_literals; namespace { +using ElectronicIDConstructor = std::function; + template constexpr auto constructor(const Reader& reader) { @@ -221,25 +224,6 @@ const auto SUPPORTED_ALGORITHMS = std::map { namespace electronic_id { -std::optional findMaskedATR(const byte_vector& atr) -{ - if (auto i = std::find(MASKED_ATRS.cbegin(), MASKED_ATRS.cend(), atr); - i != MASKED_ATRS.cend()) { - return i->constructor; - } - return std::nullopt; -} - -bool isCardSupported(const pcsc_cpp::byte_vector& atr) -{ - if (SUPPORTED_ATRS.contains(atr)) { - return true; - } - - // If exact ATR match is not found, fall back to masked ATR lookup. - return findMaskedATR(atr).has_value(); -} - ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader) { if (auto it = SUPPORTED_ATRS.find(reader.cardAtr); it != SUPPORTED_ATRS.end()) { @@ -247,13 +231,12 @@ ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader) } // If exact ATR match is not found, fall back to masked ATR lookup. - if (auto eIDConstructor = findMaskedATR(reader.cardAtr)) { - return (*eIDConstructor)(reader); + if (auto i = std::find(MASKED_ATRS.cbegin(), MASKED_ATRS.cend(), reader.cardAtr); + i != MASKED_ATRS.cend()) { + return i->constructor(reader); } - // It should be verified that the card is supported with isCardSupported() before - // calling getElectronicID(), so it is a programming error to reach this point. - THROW(ProgrammingError, "Card with ATR '" + reader.cardAtr + "' is not supported"); + return nullptr; } bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo) const diff --git a/tests/mock/test-find-masked-atr.cpp b/tests/mock/test-find-masked-atr.cpp index e949e5e9..0eeda5a8 100644 --- a/tests/mock/test-find-masked-atr.cpp +++ b/tests/mock/test-find-masked-atr.cpp @@ -22,26 +22,28 @@ #include "electronic-id/electronic-id.hpp" +#include "atrs.hpp" + #include using namespace electronic_id; -const pcsc_cpp::byte_vector BEL_EID_V1_7_ATR {0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, - 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; -const pcsc_cpp::byte_vector INVALID_ATR {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, - 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; - -TEST(electronic_id_test, findMaskedATRSuccessWithSupportedMaskedATR) -{ - EXPECT_TRUE(findMaskedATR(BEL_EID_V1_7_ATR).has_value()); -} +const pcsc_cpp::Reader INVALID_ATR { + nullptr, + {}, + {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}, + true}; -TEST(electronic_id_test, findMaskedATRFailureWithUnSupportedATR) +TEST(electronic_id_test, getElectronicIDSuccessWithSupportedMaskedATR) { - EXPECT_FALSE(findMaskedATR(INVALID_ATR).has_value()); + PcscMock::setAtr(FINEID_V4_ATR); + auto result = getElectronicID(pcsc_cpp::listReaders().front()); + EXPECT_TRUE(result); + EXPECT_EQ(result->name(), "FinEID v4"); + PcscMock::reset(); } -TEST(electronic_id_test, isCardSupportedSuccessWithSupportedMaskedATR) +TEST(electronic_id_test, getElectronicIDFailureWithUnsupportedMaskedATR) { - EXPECT_TRUE(isCardSupported(BEL_EID_V1_7_ATR)); + EXPECT_FALSE(getElectronicID(INVALID_ATR)); } diff --git a/tests/mock/test-is-card-supported.cpp b/tests/mock/test-is-card-supported.cpp index b1da7b76..f3212b38 100644 --- a/tests/mock/test-is-card-supported.cpp +++ b/tests/mock/test-is-card-supported.cpp @@ -26,18 +26,13 @@ using namespace electronic_id; -const pcsc_cpp::byte_vector EstEIDIDEMIAV1_ATR {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, - 0x1f, 0x83, 0x00, 0x12, 0x23, 0x3f, 0x53, 0x65, - 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1}; -const pcsc_cpp::byte_vector INVALID_ATR {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, - 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; +const pcsc_cpp::Reader INVALID_ATR { + nullptr, + {}, + {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}, + true}; -TEST(electronic_id_test, isCardSupportedSuccessWithSupportedATR) +TEST(electronic_id_test, getElectronicIDNullForUnsupportedATR) { - EXPECT_TRUE(isCardSupported(EstEIDIDEMIAV1_ATR)); -} - -TEST(electronic_id_test, isCardSupportedFailureWithUnsupportedATR) -{ - EXPECT_FALSE(isCardSupported(INVALID_ATR)); + EXPECT_FALSE(getElectronicID(INVALID_ATR)); } From d3dd42b7d365679004bb77254203cf4549769130 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 5 Jun 2026 13:47:52 +0300 Subject: [PATCH 2/2] Fix todo and move ATR-s to relevant classes Signed-off-by: Raul Metsma --- CMakeLists.txt | 2 +- .../include/pcsc-mock/pcsc-mock.hpp | 13 +-- .../tests/lib/libpcsc-mock/src/pcsc-mock.cpp | 1 - .../lib/libpcsc-mock/tests/pcsc-mock-test.cpp | 7 +- .../test-connect-to-card-transmit-apdus.cpp | 4 +- src/electronic-id.cpp | 83 +++++++------------ src/electronic-ids/pcsc/EstEIDIDEMIA.hpp | 7 ++ src/electronic-ids/pcsc/EstEIDThales.hpp | 4 + src/electronic-ids/pcsc/FinEID.hpp | 8 ++ src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp | 7 ++ .../pkcs11/Pkcs11ElectronicID.hpp | 11 +++ tests/mock/atrs.hpp | 44 ---------- tests/mock/test-autoselect-card.cpp | 14 ++-- tests/mock/test-find-masked-atr.cpp | 6 +- tests/mock/test-get-certificate.cpp | 13 +-- 15 files changed, 106 insertions(+), 118 deletions(-) delete mode 100644 tests/mock/atrs.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b787f99..468d625e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ add_library(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PUBLIC include + $ ) find_package(OpenSSL 3.0.0 REQUIRED) @@ -73,7 +74,6 @@ set(MOCK_TEST_EXE lib${PROJECT_NAME}-test-mock) add_executable(${MOCK_TEST_EXE} tests/common/selectcard.hpp tests/common/verify.hpp - tests/mock/atrs.hpp tests/mock/select-certificate-script.hpp tests/mock/select-certificate-script-EST-IDEMIA.hpp tests/mock/select-certificate-script-FIN-V3.hpp diff --git a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/include/pcsc-mock/pcsc-mock.hpp b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/include/pcsc-mock/pcsc-mock.hpp index 8f7ece53..b0d1bc29 100644 --- a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/include/pcsc-mock/pcsc-mock.hpp +++ b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/include/pcsc-mock/pcsc-mock.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef _WIN32 using MOCK_LONG = int32_t; @@ -44,7 +45,9 @@ class PcscMockError : public std::runtime_error class PcscMock { public: - using byte_vector = std::vector; + using byte_type = unsigned char; + using byte_vector = std::vector; + using byte_span = std::span; // An APDU script is a list of request-response APDU pairs. using ApduScript = std::vector>; // Define local string type so that we can use wstring in Windows if needed. @@ -97,10 +100,10 @@ class PcscMock self._stepCount = 0; } - static const byte_vector& atr() { return instance()._atr; } - static void setAtr(const byte_vector& atr) { instance()._atr = atr; } + static byte_span atr() { return instance()._atr; } + static void setAtr(byte_span atr) { instance()._atr = std::move(atr); } - static const byte_vector DEFAULT_CARD_ATR; + static constexpr byte_type DEFAULT_CARD_ATR[] {0x1, 0x2, 0x3, 0x4}; static const string_t DEFAULT_READER_NAME; static const byte_vector DEFAULT_COMMAND_APDU; @@ -125,7 +128,7 @@ class PcscMock std::set _recordedCalls; std::map _scardCallReturnValues; - byte_vector _atr = DEFAULT_CARD_ATR; + byte_span _atr = DEFAULT_CARD_ATR; ApduScript _script = DEFAULT_SCRIPT; size_t _stepCount = 0; }; diff --git a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/src/pcsc-mock.cpp b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/src/pcsc-mock.cpp index 96a9dc8f..83fe1584 100644 --- a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/src/pcsc-mock.cpp +++ b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/src/pcsc-mock.cpp @@ -80,7 +80,6 @@ PcscMock::byte_vector PcscMock::responseForApduCommand(const PcscMock::byte_vect return response; } -const PcscMock::byte_vector PcscMock::DEFAULT_CARD_ATR {0x1, 0x2, 0x3, 0x4}; #ifdef _WIN32 const PcscMock::string_t PcscMock::DEFAULT_READER_NAME {L"PcscMock-reader"s}; #else diff --git a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/tests/pcsc-mock-test.cpp b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/tests/pcsc-mock-test.cpp index 1e117546..dcf7644b 100644 --- a/lib/libpcsc-cpp/tests/lib/libpcsc-mock/tests/pcsc-mock-test.cpp +++ b/lib/libpcsc-cpp/tests/lib/libpcsc-mock/tests/pcsc-mock-test.cpp @@ -31,6 +31,8 @@ #include #endif +#include +#include #include #include @@ -66,9 +68,8 @@ TEST(scard_mock_test, testScardCalls) readerName = readerStates[0].szReader; EXPECT_EQ(readerName, PcscMock::DEFAULT_READER_NAME); - auto atrBuf = readerStates[0].rgbAtr; - vector atr(atrBuf, atrBuf + readerStates[0].cbAtr); - EXPECT_EQ(atr, PcscMock::DEFAULT_CARD_ATR); + EXPECT_TRUE(std::ranges::equal(std::span(readerStates[0].rgbAtr, readerStates[0].cbAtr), + PcscMock::DEFAULT_CARD_ATR)); auto protocol = SCARD_PROTOCOL_T0; DWORD protocolOut = SCARD_PROTOCOL_UNDEFINED; diff --git a/lib/libpcsc-cpp/tests/mock/test-connect-to-card-transmit-apdus.cpp b/lib/libpcsc-cpp/tests/mock/test-connect-to-card-transmit-apdus.cpp index e7bf6cdc..f9999774 100644 --- a/lib/libpcsc-cpp/tests/mock/test-connect-to-card-transmit-apdus.cpp +++ b/lib/libpcsc-cpp/tests/mock/test-connect-to-card-transmit-apdus.cpp @@ -27,6 +27,8 @@ #include +#include + using namespace pcsc_cpp; namespace @@ -46,7 +48,7 @@ TEST(pcsc_cpp_test, connectToCardSuccess) { auto card = connectToCard(); - EXPECT_EQ(card.atr(), PcscMock::DEFAULT_CARD_ATR); + EXPECT_TRUE(std::ranges::equal(card.atr(), PcscMock::DEFAULT_CARD_ATR)); EXPECT_EQ(card.protocol(), SmartCard::Protocol::T1); } diff --git a/src/electronic-id.cpp b/src/electronic-id.cpp index d6d435f3..cd9ddb18 100644 --- a/src/electronic-id.cpp +++ b/src/electronic-id.cpp @@ -29,13 +29,13 @@ #include "magic_enum/magic_enum.hpp" -#include +#include #include #include +#include using namespace pcsc_cpp; using namespace electronic_id; -using namespace std::string_literals; namespace { @@ -43,55 +43,39 @@ namespace using ElectronicIDConstructor = std::function; template -constexpr auto constructor(const Reader& reader) +ElectronicID::ptr constructor(const Reader& reader) { - return std::make_unique(reader.connectToCard()); + return std::make_shared(reader.connectToCard()); } template -constexpr auto constructor(const Reader& /*reader*/) +ElectronicID::ptr constructor(const Reader& /*reader*/) { - return std::make_unique(value); + return std::make_shared(value); } +struct ATREntry +{ + std::span atr; + ElectronicID::ptr (*constructor)(const pcsc_cpp::Reader&); + + constexpr bool operator==(const pcsc_cpp::byte_vector& other) const + { + return std::ranges::equal(atr, other); + } +}; + // Supported cards. -const std::map SUPPORTED_ATRS { - // EstEID Idemia Cosmo 8.1/8.2 - {{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00, - 0x12, 0x23, 0x3f, 0x53, 0x65, 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1}, - constructor}, - // EstEID Idemia Cosmo X - {{0x3b, 0xdc, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00, 0x12, - 0x23, 0x3f, 0x54, 0x65, 0x49, 0x44, 0x32, 0x0f, 0x90, 0x00, 0xc3}, - constructor}, - // EstEID Thales v1.0 - {{0x3b, 0xff, 0x96, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x43, 0x80, 0x31, 0xb8, 0x53, - 0x65, 0x49, 0x44, 0x64, 0xb0, 0x85, 0x05, 0x10, 0x12, 0x23, 0x3f, 0x1d}, - constructor}, - // FinEID v3.1 - {{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0, - 0x85, 0x04, 0x02, 0x1B, 0x12, 0x00, 0xF6, 0x82, 0x90, 0x00}, - constructor}, - // LatEID Idemia Cosmo 8.1/8.2 - {{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00, - 0x12, 0x42, 0x8f, 0x53, 0x65, 0x49, 0x44, 0x0f, 0x90, 0x00, 0x20}, - constructor}, - // LatEID Idemia Cosmo X - {{0x3b, 0xdc, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00, 0x12, - 0x42, 0x8f, 0x54, 0x65, 0x49, 0x44, 0x32, 0x0f, 0x90, 0x00, 0x12}, - constructor}, - // HrvEID - {{0x3b, 0xff, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe, 0x45, 0x00, 0x31, 0xb9, 0x64, - 0x04, 0x44, 0xec, 0xc1, 0x73, 0x94, 0x01, 0x80, 0x82, 0x90, 0x00, 0x12}, - constructor}, - // BelEID - https://github.com/Fedict/eid-mw/wiki/Applet-1.8 - {{0x3b, 0x7f, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0, - 0x85, 0x04, 0x01, 0x20, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00}, - constructor}, - // CzeEID - {{0x3b, 0x7e, 0x94, 0x00, 0x00, 0x80, 0x25, 0xd2, 0x03, 0x10, 0x01, 0x00, 0x56, 0x00, 0x00, - 0x00, 0x02, 0x02, 0x00}, - constructor}, +constexpr ATREntry SUPPORTED_ATRS[] { + {EstEIDIDEMIAV1::ATR_COSMO_8, constructor}, + {EstEIDIDEMIAV1::ATR_COSMO_X, constructor}, + {EstEIDThales::ATR, constructor}, + {FinEIDv3::ATR, constructor}, + {LatEIDIDEMIAV2::ATR_COSMO_8, constructor}, + {LatEIDIDEMIAV2::ATR_COSMO_X, constructor}, + {Pkcs11ElectronicID::HrvEID_ATR, constructor}, + {Pkcs11ElectronicID::BelEID_ATR, constructor}, + {Pkcs11ElectronicID::CzeEID_ATR, constructor}, }; // Holds ATR pattern, mask, and constructor for variable ATR cards. @@ -123,11 +107,7 @@ struct MaskedATREntry const std::vector MASKED_ATRS = { // FinEID Thales v4.0/v4.1 - {{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0, - 0x85, 0x05, 0x00, 0x11, 0x12, 0x24, 0x60, 0x82, 0x90, 0x00}, - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - constructor}, + {FinEIDv4::ATR, FinEIDv4::MASK, constructor}, // BelEID v1.7 {{0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}, {0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, @@ -212,7 +192,7 @@ const std::vector MASKED_ATRS = { constructor}, }; -const auto SUPPORTED_ALGORITHMS = std::map { +const std::map SUPPORTED_ALGORITHMS { {"SHA-224", HashAlgorithm::SHA224}, {"SHA-256", HashAlgorithm::SHA256}, {"SHA-384", HashAlgorithm::SHA384}, {"SHA-512", HashAlgorithm::SHA512}, {"SHA3-224", HashAlgorithm::SHA3_224}, {"SHA3-256", HashAlgorithm::SHA3_256}, @@ -226,8 +206,9 @@ namespace electronic_id ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader) { - if (auto it = SUPPORTED_ATRS.find(reader.cardAtr); it != SUPPORTED_ATRS.end()) { - return it->second(reader); + if (auto it = std::find(std::begin(SUPPORTED_ATRS), std::end(SUPPORTED_ATRS), reader.cardAtr); + it != std::end(SUPPORTED_ATRS)) { + return it->constructor(reader); } // If exact ATR match is not found, fall back to masked ATR lookup. diff --git a/src/electronic-ids/pcsc/EstEIDIDEMIA.hpp b/src/electronic-ids/pcsc/EstEIDIDEMIA.hpp index bed9c2e1..56e5b405 100644 --- a/src/electronic-ids/pcsc/EstEIDIDEMIA.hpp +++ b/src/electronic-ids/pcsc/EstEIDIDEMIA.hpp @@ -35,6 +35,13 @@ class EstEIDIDEMIAV1 : public EIDIDEMIA public: using EIDIDEMIA::EIDIDEMIA; + static constexpr byte_type ATR_COSMO_8[] {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, + 0x1f, 0x83, 0x00, 0x12, 0x23, 0x3f, 0x53, 0x65, + 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1}; + static constexpr byte_type ATR_COSMO_X[] {0x3b, 0xdc, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, + 0x1f, 0x83, 0x00, 0x12, 0x23, 0x3f, 0x54, 0x65, + 0x49, 0x44, 0x32, 0x0f, 0x90, 0x00, 0xc3}; + private: constexpr PinMinMaxLength signingPinMinMaxLength() const override { return {5, 12}; } std::string name() const override { return "EstEID IDEMIA v1"; } diff --git a/src/electronic-ids/pcsc/EstEIDThales.hpp b/src/electronic-ids/pcsc/EstEIDThales.hpp index fa5c6415..c692bf5e 100644 --- a/src/electronic-ids/pcsc/EstEIDThales.hpp +++ b/src/electronic-ids/pcsc/EstEIDThales.hpp @@ -32,6 +32,10 @@ class EstEIDThales : public EIDThales public: using EIDThales::EIDThales; + static constexpr byte_type ATR[] {0x3b, 0xff, 0x96, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x43, + 0x80, 0x31, 0xb8, 0x53, 0x65, 0x49, 0x44, 0x64, 0xb0, + 0x85, 0x05, 0x10, 0x12, 0x23, 0x3f, 0x1d}; + protected: std::string name() const override { return "EstEIDThales"; } Type type() const override { return EstEID; } diff --git a/src/electronic-ids/pcsc/FinEID.hpp b/src/electronic-ids/pcsc/FinEID.hpp index 562bb031..5a0b5e02 100644 --- a/src/electronic-ids/pcsc/FinEID.hpp +++ b/src/electronic-ids/pcsc/FinEID.hpp @@ -32,6 +32,11 @@ class FinEIDv4 : public EIDThales public: using EIDThales::EIDThales; + static constexpr byte_type ATR[] {0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0, + 0x85, 0x05, 0x00, 0x11, 0x12, 0x24, 0x60, 0x82, 0x90, 0x00}; + static constexpr byte_type MASK[] {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + protected: std::string name() const override { return "FinEID v4"; } Type type() const override { return FinEID; } @@ -54,6 +59,9 @@ class FinEIDv3 : public FinEIDv4 public: using FinEIDv4::FinEIDv4; + static constexpr byte_type ATR[] {0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0, + 0x85, 0x04, 0x02, 0x1B, 0x12, 0x00, 0xF6, 0x82, 0x90, 0x00}; + protected: std::string name() const override { return "FinEID v3"; } constexpr JsonWebSignatureAlgorithm authSignatureAlgorithm() const override diff --git a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp index 112d833c..fce118f6 100644 --- a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp +++ b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp @@ -38,6 +38,13 @@ class LatEIDIDEMIAV2 : public EIDIDEMIA ~LatEIDIDEMIAV2() override; PCSC_CPP_DISABLE_COPY_MOVE(LatEIDIDEMIAV2); + static constexpr byte_type ATR_COSMO_8[] {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, + 0x1f, 0x83, 0x00, 0x12, 0x42, 0x8f, 0x53, 0x65, + 0x49, 0x44, 0x0f, 0x90, 0x00, 0x20}; + static constexpr byte_type ATR_COSMO_X[] {0x3b, 0xdc, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, + 0x1f, 0x83, 0x00, 0x12, 0x42, 0x8f, 0x54, 0x65, + 0x49, 0x44, 0x32, 0x0f, 0x90, 0x00, 0x12}; + private: byte_vector getCertificateImpl(const SmartCard::Session& session, const CertificateType type) const override; diff --git a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.hpp b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.hpp index 4498af5b..b80d3cb4 100644 --- a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.hpp +++ b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.hpp @@ -45,6 +45,17 @@ class Pkcs11ElectronicID : public ElectronicID public: explicit Pkcs11ElectronicID(ElectronicID::Type type); + static constexpr byte_type HrvEID_ATR[] {0x3b, 0xff, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe, 0x45, + 0x00, 0x31, 0xb9, 0x64, 0x04, 0x44, 0xec, 0xc1, 0x73, + 0x94, 0x01, 0x80, 0x82, 0x90, 0x00, 0x12}; + // https://github.com/Fedict/eid-mw/wiki/Applet-1.8 + static constexpr byte_type BelEID_ATR[] {0x3b, 0x7f, 0x96, 0x00, 0x00, 0x80, 0x31, + 0x80, 0x65, 0xb0, 0x85, 0x04, 0x01, 0x20, + 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00}; + static constexpr byte_type CzeEID_ATR[] {0x3b, 0x7e, 0x94, 0x00, 0x00, 0x80, 0x25, + 0xd2, 0x03, 0x10, 0x01, 0x00, 0x56, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00}; + private: bool allowsUsingLettersAndSpecialCharactersInPin() const override { diff --git a/tests/mock/atrs.hpp b/tests/mock/atrs.hpp deleted file mode 100644 index fca8aa7d..00000000 --- a/tests/mock/atrs.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020-2024 Estonian Information System Authority - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "pcsc-mock/pcsc-mock.hpp" - -// TODO: expose ATRs from electronic-id.cpp (currently local variables there) -// to avoid duplication. - -const PcscMock::byte_vector ESTEID_IDEMIA_V1_ATR {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, - 0x1f, 0x83, 0x00, 0x12, 0x23, 0x3f, 0x53, 0x65, - 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1}; - -const PcscMock::byte_vector LATEID_IDEMIA_V2_ATR {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, - 0x1f, 0x83, 0x00, 0x12, 0x42, 0x8f, 0x53, 0x65, - 0x49, 0x44, 0x0f, 0x90, 0x00, 0x20}; - -const PcscMock::byte_vector FINEID_V3_ATR {0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, - 0xB8, 0x65, 0xB0, 0x85, 0x04, 0x02, 0x1B, - 0x12, 0x00, 0xF6, 0x82, 0x90, 0x00}; - -const PcscMock::byte_vector FINEID_V4_ATR {0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, - 0xB8, 0x65, 0xB0, 0x85, 0x05, 0x00, 0x11, - 0x12, 0x24, 0x60, 0x82, 0x90, 0x00}; diff --git a/tests/mock/test-autoselect-card.cpp b/tests/mock/test-autoselect-card.cpp index 044c915f..c28629fd 100644 --- a/tests/mock/test-autoselect-card.cpp +++ b/tests/mock/test-autoselect-card.cpp @@ -22,7 +22,11 @@ #include "../common/selectcard.hpp" -#include "atrs.hpp" +#include "electronic-ids/pcsc/EstEIDIDEMIA.hpp" +#include "electronic-ids/pcsc/FinEID.hpp" +#include "electronic-ids/pcsc/LatEIDIDEMIAv2.hpp" + +#include "pcsc-mock/pcsc-mock.hpp" #include @@ -35,7 +39,7 @@ TEST(electronic_id_test, autoSelectFailureWithUnsupportedCard) TEST(electronic_id_test, autoSelectSuccessWithSupportedCardEstIDEMIA) { - PcscMock::setAtr(ESTEID_IDEMIA_V1_ATR); + PcscMock::setAtr(EstEIDIDEMIAV1::ATR_COSMO_8); auto result = autoSelectSupportedCard(); EXPECT_TRUE(result); EXPECT_EQ(result->name(), "EstEID IDEMIA v1"); @@ -44,7 +48,7 @@ TEST(electronic_id_test, autoSelectSuccessWithSupportedCardEstIDEMIA) TEST(electronic_id_test, autoSelectSuccessWithSupportedCardLatV2) { - PcscMock::setAtr(LATEID_IDEMIA_V2_ATR); + PcscMock::setAtr(LatEIDIDEMIAV2::ATR_COSMO_8); auto result = autoSelectSupportedCard(); EXPECT_TRUE(result); EXPECT_EQ(result->name(), "LatEID IDEMIA v2"); @@ -53,7 +57,7 @@ TEST(electronic_id_test, autoSelectSuccessWithSupportedCardLatV2) TEST(electronic_id_test, autoSelectSuccessWithSupportedCardFinV3) { - PcscMock::setAtr(FINEID_V3_ATR); + PcscMock::setAtr(FinEIDv3::ATR); auto result = autoSelectSupportedCard(); EXPECT_TRUE(result); EXPECT_EQ(result->name(), "FinEID v3"); @@ -62,7 +66,7 @@ TEST(electronic_id_test, autoSelectSuccessWithSupportedCardFinV3) TEST(electronic_id_test, autoSelectSuccessWithSupportedCardFinV4) { - PcscMock::setAtr(FINEID_V4_ATR); + PcscMock::setAtr(FinEIDv4::ATR); auto result = autoSelectSupportedCard(); EXPECT_TRUE(result); EXPECT_EQ(result->name(), "FinEID v4"); diff --git a/tests/mock/test-find-masked-atr.cpp b/tests/mock/test-find-masked-atr.cpp index 0eeda5a8..4f6c88f1 100644 --- a/tests/mock/test-find-masked-atr.cpp +++ b/tests/mock/test-find-masked-atr.cpp @@ -22,7 +22,9 @@ #include "electronic-id/electronic-id.hpp" -#include "atrs.hpp" +#include "electronic-ids/pcsc/FinEID.hpp" + +#include "pcsc-mock/pcsc-mock.hpp" #include @@ -36,7 +38,7 @@ const pcsc_cpp::Reader INVALID_ATR { TEST(electronic_id_test, getElectronicIDSuccessWithSupportedMaskedATR) { - PcscMock::setAtr(FINEID_V4_ATR); + PcscMock::setAtr(FinEIDv4::ATR); auto result = getElectronicID(pcsc_cpp::listReaders().front()); EXPECT_TRUE(result); EXPECT_EQ(result->name(), "FinEID v4"); diff --git a/tests/mock/test-get-certificate.cpp b/tests/mock/test-get-certificate.cpp index 1359f10b..41143ba0 100644 --- a/tests/mock/test-get-certificate.cpp +++ b/tests/mock/test-get-certificate.cpp @@ -23,8 +23,11 @@ #include "../common/selectcard.hpp" #include "../common/verify.hpp" +#include "electronic-ids/pcsc/EstEIDIDEMIA.hpp" +#include "electronic-ids/pcsc/FinEID.hpp" +#include "electronic-ids/pcsc/LatEIDIDEMIAv2.hpp" + #include "select-certificate-script.hpp" -#include "atrs.hpp" #include @@ -37,7 +40,7 @@ const pcsc_cpp::byte_vector dataToSign {'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', TEST(electronic_id_test, selectCertificateEstIDEMIA) { - PcscMock::setAtr(ESTEID_IDEMIA_V1_ATR); + PcscMock::setAtr(EstEIDIDEMIAV1::ATR_COSMO_8); auto cardInfo = autoSelectSupportedCard(); EXPECT_TRUE(cardInfo); EXPECT_EQ(cardInfo->name(), "EstEID IDEMIA v1"); @@ -86,7 +89,7 @@ TEST(electronic_id_test, selectCertificateEstIDEMIA) TEST(electronic_id_test, selectCertificateFinV3) { - PcscMock::setAtr(FINEID_V3_ATR); + PcscMock::setAtr(FinEIDv3::ATR); auto cardInfo = autoSelectSupportedCard(); EXPECT_TRUE(cardInfo); @@ -136,7 +139,7 @@ TEST(electronic_id_test, selectCertificateFinV3) TEST(electronic_id_test, selectCertificateFinV4) { - PcscMock::setAtr(FINEID_V4_ATR); + PcscMock::setAtr(FinEIDv4::ATR); auto cardInfo = autoSelectSupportedCard(); EXPECT_TRUE(cardInfo); @@ -186,7 +189,7 @@ TEST(electronic_id_test, selectCertificateFinV4) TEST(electronic_id_test, selectCertificateLatV2) { - PcscMock::setAtr(LATEID_IDEMIA_V2_ATR); + PcscMock::setAtr(LatEIDIDEMIAV2::ATR_COSMO_8); auto cardInfo = autoSelectSupportedCard(); EXPECT_TRUE(cardInfo);