diff --git a/.github/workflows/cmake-windows.yml b/.github/workflows/cmake-windows.yml index 5d735c3..bed214b 100644 --- a/.github/workflows/cmake-windows.yml +++ b/.github/workflows/cmake-windows.yml @@ -19,7 +19,7 @@ jobs: with: vcpkgArguments: gtest:x64-windows openssl:x64-windows vcpkgTriplet: x64-windows - vcpkgGitCommitId: 0d5cae153065957df7f382de7c1549ccc88027e5 + vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e - name: Configure CMake run: cmake -A x64 "-DCMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" "-DCMAKE_BUILD_TYPE=${env:BUILD_TYPE}" -S . -B build diff --git a/include/electronic-id/electronic-id.hpp b/include/electronic-id/electronic-id.hpp index 006a47e..ba46e3b 100644 --- a/include/electronic-id/electronic-id.hpp +++ b/include/electronic-id/electronic-id.hpp @@ -98,12 +98,12 @@ class ElectronicID virtual std::string name() const = 0; virtual Type type() const = 0; - virtual pcsc_cpp::SmartCard const& smartcard() const { return *card; } + virtual pcsc_cpp::SmartCard const& smartcard() const { return card; } protected: - ElectronicID(pcsc_cpp::SmartCard::ptr _card) : card(std::move(_card)) {} + ElectronicID(pcsc_cpp::SmartCard&& _card) noexcept : card(std::move(_card)) {} - pcsc_cpp::SmartCard::ptr card; + pcsc_cpp::SmartCard card; }; using ElectronicIDConstructor = std::function; diff --git a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp index 9e12ecb..852447e 100644 --- a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp +++ b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp @@ -30,9 +30,11 @@ #include // The rule of five (C++ Core guidelines C.21). -#define PCSC_CPP_DISABLE_COPY_MOVE(Class) \ +#define PCSC_CPP_DISABLE_COPY(Class) \ Class(const Class&) = delete; \ - Class& operator=(const Class&) = delete; \ + Class& operator=(const Class&) = delete +#define PCSC_CPP_DISABLE_COPY_MOVE(Class) \ + PCSC_CPP_DISABLE_COPY(Class); \ Class(Class&&) = delete; \ Class& operator=(Class&&) = delete @@ -235,7 +237,19 @@ struct CommandApdu /** Opaque class that wraps the PC/SC smart card resources like card handle and I/O protocol. */ class CardImpl; -using CardImplPtr = std::unique_ptr; + +class SmartCard; + +/** Reader provides card reader information, status and gives access to the smart card in it. */ +struct Reader +{ + [[nodiscard]] SmartCard connectToCard() const; + + const ContextPtr ctx; + const string_t name; + const byte_vector cardAtr; + const bool isCardPresent = false; +}; /** PIN pad PIN entry timer timeout */ constexpr uint8_t PIN_PAD_PIN_ENTRY_TIMEOUT = 90; // 1 minute, 30 seconds @@ -246,52 +260,37 @@ class SmartCard public: enum class Protocol { UNDEFINED, T0, T1 }; // AUTO = T0 | T1 - using ptr = std::unique_ptr; - - class TransactionGuard + class Session { public: - TransactionGuard(const CardImpl& CardImpl, bool& inProgress); - ~TransactionGuard() noexcept; - PCSC_CPP_DISABLE_COPY_MOVE(TransactionGuard); + Session(const CardImpl& CardImpl); + ~Session() noexcept; + PCSC_CPP_DISABLE_COPY_MOVE(Session); + + ResponseApdu transmit(const CommandApdu& command) const; + ResponseApdu transmitCTL(const CommandApdu& command, uint16_t lang, uint8_t minlen) const; + bool readerHasPinPad() const; private: const CardImpl& card; - bool& inProgress; }; - SmartCard(ContextPtr context, string_t readerName, byte_vector atr); - SmartCard(); // Null object constructor. + SmartCard(Reader _reader); + SmartCard() noexcept; // Null object constructor. + SmartCard(SmartCard&& other) noexcept; ~SmartCard() noexcept; - PCSC_CPP_DISABLE_COPY_MOVE(SmartCard); + PCSC_CPP_DISABLE_COPY(SmartCard); + SmartCard& operator=(SmartCard&& other) noexcept = delete; - TransactionGuard beginTransaction(); - ResponseApdu transmit(const CommandApdu& command) const; - ResponseApdu transmitCTL(const CommandApdu& command, uint16_t lang, uint8_t minlen) const; + [[nodiscard]] Session beginSession() const; bool readerHasPinPad() const; - - Protocol protocol() const { return _protocol; } - const byte_vector& atr() const { return _atr; } - const string_t& readerName() const { return _readerName; } + Protocol protocol() const; + const byte_vector& atr() const { return reader.cardAtr; } + const string_t& readerName() const { return reader.name; } private: - ContextPtr ctx; - CardImplPtr card; - string_t _readerName; - byte_vector _atr; - Protocol _protocol = Protocol::UNDEFINED; - bool transactionInProgress = false; -}; - -/** Reader provides card reader information, status and gives access to the smart card in it. */ -struct Reader -{ - SmartCard::ptr connectToCard() const { return std::make_unique(ctx, name, cardAtr); } - - const ContextPtr ctx; - const string_t name; - const byte_vector cardAtr; - const bool isCardPresent; + Reader reader; + std::unique_ptr card; }; /** @@ -304,10 +303,12 @@ std::vector listReaders(); // Utility functions. /** Transmit APDU command and verify that expected response is received. */ -void transmitApduWithExpectedResponse(const SmartCard& card, const CommandApdu& command); +void transmitApduWithExpectedResponse(const SmartCard::Session& session, + const CommandApdu& command); /** Read lenght bytes from currently selected binary file in blockLength-sized chunks. */ -byte_vector readBinary(const SmartCard& card, const uint16_t length, byte_type blockLength = 0x00); +byte_vector readBinary(const SmartCard::Session& session, const uint16_t length, + byte_type blockLength = 0x00); // Errors. diff --git a/lib/libpcsc-cpp/src/SmartCard.cpp b/lib/libpcsc-cpp/src/SmartCard.cpp index 5bf327c..3e2f0b9 100644 --- a/lib/libpcsc-cpp/src/SmartCard.cpp +++ b/lib/libpcsc-cpp/src/SmartCard.cpp @@ -41,35 +41,6 @@ namespace { -using namespace pcsc_cpp; - -constexpr SmartCard::Protocol convertToSmartCardProtocol(const DWORD protocol) -{ - switch (protocol) { - case SCARD_PROTOCOL_UNDEFINED: - return SmartCard::Protocol::UNDEFINED; - case SCARD_PROTOCOL_T0: - return SmartCard::Protocol::T0; - case SCARD_PROTOCOL_T1: - return SmartCard::Protocol::T1; - default: - THROW(Error, "Unsupported card protocol: " + std::to_string(protocol)); - } -} - -std::pair connectToCard(const SCARDCONTEXT ctx, const string_t& readerName) -{ - const unsigned requestedProtocol = - SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; // Let PCSC auto-select protocol. - DWORD protocolOut = SCARD_PROTOCOL_UNDEFINED; - SCARDHANDLE cardHandle = 0; - - SCard(Connect, ctx, readerName.c_str(), DWORD(SCARD_SHARE_SHARED), requestedProtocol, - &cardHandle, &protocolOut); - - return {cardHandle, protocolOut}; -} - template constexpr std::map parseTLV(const std::array& data, DWORD size, Func transform) { @@ -93,21 +64,35 @@ constexpr uint32_t OMNIKEY_6121 = 0x6632; namespace pcsc_cpp { +SmartCard Reader::connectToCard() const +{ + return {*this}; +} + class CardImpl { public: - explicit CardImpl(std::pair cardParams) : - cardHandle(cardParams.first), _protocol {cardParams.second, sizeof(SCARD_IO_REQUEST)} + explicit CardImpl(const Reader& reader) { - // TODO: debug("Protocol: " + to_string(protocol())) + constexpr unsigned requestedProtocol = + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; // Let PCSC auto-select protocol. + SCard(Connect, reader.ctx->handle(), reader.name.c_str(), DWORD(SCARD_SHARE_SHARED), + requestedProtocol, &cardHandle, &_protocol.dwProtocol); + try { DWORD size = 0; - std::array buf {}; - SCard(Control, cardHandle, DWORD(CM_IOCTL_GET_FEATURE_REQUEST), nullptr, 0U, buf.data(), - DWORD(buf.size()), &size); - features = parseTLV(buf, size, [](uint32_t t) { return ntohl(t); }); + std::array list {}; + SCard(Control, cardHandle, DWORD(CM_IOCTL_GET_FEATURE_REQUEST), nullptr, 0U, + list.data(), DWORD(list.size() * sizeof(PCSC_TLV_STRUCTURE)), &size); + if (size == 0 || size % sizeof(PCSC_TLV_STRUCTURE)) { + return; // No features available or malformed response. + } + for (const auto& f : list) { + features[DRIVER_FEATURES(f.tag)] = ntohl(f.value); + } if (auto ioctl = features.find(FEATURE_GET_TLV_PROPERTIES); ioctl != features.cend()) { + std::array buf {}; SCard(Control, cardHandle, ioctl->second, nullptr, 0U, buf.data(), DWORD(buf.size()), &size); auto properties = parseTLV(buf, size, [](uint32_t t) { return t; }); @@ -124,7 +109,7 @@ class CardImpl } } - ~CardImpl() + ~CardImpl() noexcept { if (cardHandle) { // Cannot throw in destructor, so cannot use the SCard() macro here. @@ -210,11 +195,24 @@ class CardImpl void endTransaction() const { SCard(EndTransaction, cardHandle, DWORD(SCARD_LEAVE_CARD)); } - DWORD protocol() const { return _protocol.dwProtocol; } + SmartCard::Protocol protocol() const + { + switch (_protocol.dwProtocol) { + using enum SmartCard::Protocol; + case SCARD_PROTOCOL_UNDEFINED: + return UNDEFINED; + case SCARD_PROTOCOL_T0: + return T0; + case SCARD_PROTOCOL_T1: + return T1; + default: + THROW(Error, "Unsupported card protocol: " + std::to_string(_protocol.dwProtocol)); + } + } private: - SCARDHANDLE cardHandle; - const SCARD_IO_REQUEST _protocol; + SCARDHANDLE cardHandle {}; + SCARD_IO_REQUEST _protocol {SCARD_PROTOCOL_UNDEFINED, sizeof(SCARD_IO_REQUEST)}; std::map features; uint32_t id_vendor {}; uint32_t id_product {}; @@ -243,7 +241,8 @@ class CardImpl break; default: THROW(Error, - "Error response: '" + response + "', protocol " + std::to_string(protocol())); + "Error response: '" + response + "', protocol " + + std::to_string(_protocol.dwProtocol)); } if (response.sw1 == ResponseApdu::WRONG_LE_LENGTH) { @@ -271,16 +270,13 @@ class CardImpl } }; -SmartCard::TransactionGuard::TransactionGuard(const CardImpl& card, bool& inProgress) : - card(card), inProgress(inProgress) +SmartCard::Session::Session(const CardImpl& card) : card(card) { card.beginTransaction(); - inProgress = true; } -SmartCard::TransactionGuard::~TransactionGuard() noexcept +SmartCard::Session::~Session() noexcept { - inProgress = false; try { card.endTransaction(); } catch (...) { @@ -288,47 +284,45 @@ SmartCard::TransactionGuard::~TransactionGuard() noexcept } } -SmartCard::SmartCard(ContextPtr context, string_t readerName, byte_vector atr) : - ctx(std::move(context)), - card(std::make_unique(connectToCard(ctx->handle(), readerName))), - _readerName(std::move(readerName)), _atr(std::move(atr)), - _protocol(convertToSmartCardProtocol(card->protocol())) +ResponseApdu SmartCard::Session::transmit(const CommandApdu& command) const { - // TODO: debug("Card ATR -> " + bytes2hexstr(atr)) + return card.transmitBytes(command); } -SmartCard::SmartCard() = default; -SmartCard::~SmartCard() noexcept = default; +ResponseApdu SmartCard::Session::transmitCTL(const CommandApdu& command, uint16_t lang, + uint8_t minlen) const +{ + return card.transmitBytesCTL(command, lang, minlen); +} -SmartCard::TransactionGuard SmartCard::beginTransaction() +bool SmartCard::Session::readerHasPinPad() const { - REQUIRE_NON_NULL(card) - return {*card, transactionInProgress}; + return card.readerHasPinPad(); } -bool SmartCard::readerHasPinPad() const +SmartCard::SmartCard(Reader _reader) : + reader(std::move(_reader)), card(std::make_unique(reader)) { - return card ? card->readerHasPinPad() : false; } -ResponseApdu SmartCard::transmit(const CommandApdu& command) const +SmartCard::SmartCard() noexcept = default; +SmartCard::SmartCard(SmartCard&& other) noexcept = default; +SmartCard::~SmartCard() noexcept = default; + +SmartCard::Session SmartCard::beginSession() const { REQUIRE_NON_NULL(card) - if (!transactionInProgress) { - THROW(std::logic_error, "Call SmartCard::transmit() inside a transaction"); - } - - return card->transmitBytes(command); + return {*card}; } -ResponseApdu SmartCard::transmitCTL(const CommandApdu& command, uint16_t lang, uint8_t minlen) const +SmartCard::Protocol SmartCard::protocol() const { - REQUIRE_NON_NULL(card) - if (!transactionInProgress) { - THROW(std::logic_error, "Call SmartCard::transmit() inside a transaction"); - } + return card ? card->protocol() : Protocol::UNDEFINED; +} - return card->transmitBytesCTL(command, lang, minlen); +bool SmartCard::readerHasPinPad() const +{ + return card ? card->readerHasPinPad() : false; } } // namespace pcsc_cpp diff --git a/lib/libpcsc-cpp/src/utils.cpp b/lib/libpcsc-cpp/src/utils.cpp index e5d8d73..005bd36 100644 --- a/lib/libpcsc-cpp/src/utils.cpp +++ b/lib/libpcsc-cpp/src/utils.cpp @@ -67,21 +67,23 @@ std::string operator+(std::string lhs, const byte_vector& rhs) return hexStringBuilder.str(); } -void transmitApduWithExpectedResponse(const SmartCard& card, const CommandApdu& command) +void transmitApduWithExpectedResponse(const SmartCard::Session& session, const CommandApdu& command) { - const auto response = card.transmit(command); + const auto response = session.transmit(command); if (!response.isOK()) { throw UnexpectedResponseError(command, response, __FILE__, __LINE__, __func__); } } -byte_vector readBinary(const SmartCard& card, const uint16_t length, byte_type blockLength) +byte_vector readBinary(const SmartCard::Session& session, const uint16_t length, + byte_type blockLength) { byte_vector resultBytes; resultBytes.reserve(length); while (resultBytes.size() < length) { byte_type chunk = byte_type(std::min(length - resultBytes.size(), blockLength)); - auto response = card.transmit(CommandApdu::readBinary(uint16_t(resultBytes.size()), chunk)); + auto response = + session.transmit(CommandApdu::readBinary(uint16_t(resultBytes.size()), chunk)); if (chunk > 0 && response.data.size() != chunk) { THROW(Error, "Length mismatch, expected "s + std::to_string(chunk) + ", received " 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 3813818..e7bf6cd 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 @@ -32,7 +32,7 @@ using namespace pcsc_cpp; namespace { -SmartCard::ptr connectToCard() +SmartCard connectToCard() { auto readers = listReaders(); EXPECT_EQ(readers.size(), 1U); @@ -46,8 +46,8 @@ TEST(pcsc_cpp_test, connectToCardSuccess) { auto card = connectToCard(); - EXPECT_EQ(card->atr(), PcscMock::DEFAULT_CARD_ATR); - EXPECT_EQ(card->protocol(), SmartCard::Protocol::T1); + EXPECT_EQ(card.atr(), PcscMock::DEFAULT_CARD_ATR); + EXPECT_EQ(card.protocol(), SmartCard::Protocol::T1); } TEST(pcsc_cpp_test, transmitApduSuccess) @@ -57,8 +57,8 @@ TEST(pcsc_cpp_test, transmitApduSuccess) CommandApdu command {PcscMock::DEFAULT_COMMAND_APDU[0], PcscMock::DEFAULT_COMMAND_APDU[1], PcscMock::DEFAULT_COMMAND_APDU[2], PcscMock::DEFAULT_COMMAND_APDU[3]}; - auto transactionGuard = card->beginTransaction(); - auto response = card->transmit(command); + auto session = card.beginSession(); + auto response = session.transmit(command); EXPECT_TRUE(response.isOK()); } diff --git a/src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp b/src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp index 7abc53a..ff9f25d 100644 --- a/src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp +++ b/src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp @@ -36,8 +36,7 @@ class MsCryptoApiElectronicID : public ElectronicID public: MsCryptoApiElectronicID(PCCERT_CONTEXT certCtx, byte_vector&& cert, CertificateType cType, bool isRsa, HCRYPTPROV_OR_NCRYPT_KEY_HANDLE k, bool freeK) : - ElectronicID {std::make_unique()}, certContext {certCtx}, - certData {cert}, certType {cType}, + ElectronicID {{}}, certContext {certCtx}, certData {cert}, certType {cType}, // TODO: SignatureAlgorithm::PS? signatureAlgo {isRsa ? SignatureAlgorithm::RS : SignatureAlgorithm::ES}, key {k}, freeKey {freeK} diff --git a/src/electronic-ids/pcsc/EIDIDEMIA.cpp b/src/electronic-ids/pcsc/EIDIDEMIA.cpp index 09211c7..07a8c3e 100644 --- a/src/electronic-ids/pcsc/EIDIDEMIA.cpp +++ b/src/electronic-ids/pcsc/EIDIDEMIA.cpp @@ -51,68 +51,71 @@ const auto SIGN_CERT = CommandApdu::selectEF(0x09, {0xAD, 0xF2, 0x34, 0x1F}); } // namespace -void EIDIDEMIA::selectMain() const +void EIDIDEMIA::selectMain(const SmartCard::Session& session) { - transmitApduWithExpectedResponse(*card, MAIN_AID); + transmitApduWithExpectedResponse(session, MAIN_AID); } -void EIDIDEMIA::selectADF1() const +void EIDIDEMIA::selectADF1(const pcsc_cpp::SmartCard::Session& session) { - transmitApduWithExpectedResponse(*card, ADF1_AID); + transmitApduWithExpectedResponse(session, ADF1_AID); } -void EIDIDEMIA::selectADF2() const +void EIDIDEMIA::selectADF2(const pcsc_cpp::SmartCard::Session& session) { - transmitApduWithExpectedResponse(*card, ADF2_AID); + transmitApduWithExpectedResponse(session, ADF2_AID); } -byte_vector EIDIDEMIA::getCertificateImpl(const CertificateType type) const +byte_vector EIDIDEMIA::getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const { - selectMain(); + selectMain(session); // Set block lenght to 0xC0 to workaround for the 2018 v2 card, with reader Alcor Micro AU9540 - return readFile(*card, type.isAuthentication() ? AUTH_CERT : SIGN_CERT, 0xC0); + return readFile(session, type.isAuthentication() ? AUTH_CERT : SIGN_CERT, 0xC0); } -EIDIDEMIA::KeyInfo EIDIDEMIA::authKeyRef() const +EIDIDEMIA::KeyInfo EIDIDEMIA::authKeyRef(const pcsc_cpp::SmartCard::Session& /*session*/) const { return {DEFAULT_AUTH_KEY_ID, true}; } -byte_vector EIDIDEMIA::signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const +byte_vector EIDIDEMIA::signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, + byte_vector&& pin, const byte_vector& hash) const { - selectADF1(); - auto [keyId, isECC] = authKeyRef(); - selectSecurityEnv(*card, 0xA4, isECC ? 0x04 : 0x02, keyId, name()); + selectADF1(session); + auto [keyId, isECC] = authKeyRef(session); + selectSecurityEnv(session, 0xA4, isECC ? 0x04 : 0x02, keyId, name()); - verifyPin(*card, AUTH_PIN_REFERENCE, std::move(pin), authPinMinMaxLength().first, + verifyPin(session, AUTH_PIN_REFERENCE, std::move(pin), authPinMinMaxLength().first, authPinMinMaxLength().second, PIN_PADDING_CHAR); - return internalAuthenticate(*card, + return internalAuthenticate(session, authSignatureAlgorithm().isRSAWithPKCS1Padding() ? addRSAOID(authSignatureAlgorithm().hashAlgorithm(), hash) : hash, name()); } -ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::authPinRetriesLeftImpl() const +ElectronicID::PinRetriesRemainingAndMax +EIDIDEMIA::authPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const { - selectMain(); - return pinRetriesLeft(AUTH_PIN_REFERENCE); + selectMain(session); + return pinRetriesLeft(session, AUTH_PIN_REFERENCE); } -EIDIDEMIA::KeyInfo EIDIDEMIA::signKeyRef() const +EIDIDEMIA::KeyInfo EIDIDEMIA::signKeyRef(const pcsc_cpp::SmartCard::Session& /*session*/) const { return {DEFAULT_SIGN_KEY_ID, true}; } -ElectronicID::Signature EIDIDEMIA::signWithSigningKeyImpl(byte_vector&& pin, - const byte_vector& hash, - const HashAlgorithm hashAlgo) const +ElectronicID::Signature +EIDIDEMIA::signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const { - selectADF2(); - auto [keyRef, isECC] = signKeyRef(); - selectSecurityEnv(*card, 0xB6, isECC ? 0x54 : 0x42, keyRef, name()); - verifyPin(*card, SIGN_PIN_REFERENCE, std::move(pin), signingPinMinMaxLength().first, + selectADF2(session); + auto [keyRef, isECC] = signKeyRef(session); + selectSecurityEnv(session, 0xB6, isECC ? 0x54 : 0x42, keyRef, name()); + verifyPin(session, SIGN_PIN_REFERENCE, std::move(pin), signingPinMinMaxLength().first, signingPinMinMaxLength().second, PIN_PADDING_CHAR); auto tmp = hash; if (isECC) { @@ -125,22 +128,24 @@ ElectronicID::Signature EIDIDEMIA::signWithSigningKeyImpl(byte_vector&& pin, tmp.resize(ECDSA384_INPUT_LENGTH); } } - return {computeSignature(*card, tmp, name()), + return {computeSignature(session, tmp, name()), {isECC ? SignatureAlgorithm::ES : SignatureAlgorithm::RS, hashAlgo}}; } -ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::signingPinRetriesLeftImpl() const +ElectronicID::PinRetriesRemainingAndMax +EIDIDEMIA::signingPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const { - selectADF2(); - return pinRetriesLeft(SIGN_PIN_REFERENCE); + selectADF2(session); + return pinRetriesLeft(session, SIGN_PIN_REFERENCE); } -ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::pinRetriesLeft(byte_type pinReference) const +ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::pinRetriesLeft(const SmartCard::Session& session, + byte_type pinReference) { auto ref = byte_type(pinReference & 0x0F); const pcsc_cpp::CommandApdu GET_DATA_ODD { 0x00, 0xCB, 0x3F, 0xFF, {0x4D, 0x08, 0x70, 0x06, 0xBF, 0x81, ref, 0x02, 0xA0, 0x80}, 0x00}; - const auto response = card->transmit(GET_DATA_ODD); + const auto response = session.transmit(GET_DATA_ODD); if (!response.isOK()) { THROW(SmartCardError, "Command GET DATA ODD failed with error " + response); } diff --git a/src/electronic-ids/pcsc/EIDIDEMIA.hpp b/src/electronic-ids/pcsc/EIDIDEMIA.hpp index b1d5381..29f3d77 100644 --- a/src/electronic-ids/pcsc/EIDIDEMIA.hpp +++ b/src/electronic-ids/pcsc/EIDIDEMIA.hpp @@ -36,33 +36,39 @@ class EIDIDEMIA : public PcscElectronicID bool isECC; }; - explicit EIDIDEMIA(pcsc_cpp::SmartCard::ptr _card) : PcscElectronicID(std::move(_card)) {} + using PcscElectronicID::PcscElectronicID; protected: - byte_vector getCertificateImpl(const CertificateType type) const override; + byte_vector getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const override; - PinRetriesRemainingAndMax authPinRetriesLeftImpl() const override; + PinRetriesRemainingAndMax + authPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const override; JsonWebSignatureAlgorithm authSignatureAlgorithm() const override { return JsonWebSignatureAlgorithm::ES384; } - virtual KeyInfo authKeyRef() const; - byte_vector signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const override; + virtual KeyInfo authKeyRef(const pcsc_cpp::SmartCard::Session& session) const; + byte_vector signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash) const override; - PinRetriesRemainingAndMax signingPinRetriesLeftImpl() const override; + PinRetriesRemainingAndMax + signingPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const override; const std::set& supportedSigningAlgorithms() const override { return ELLIPTIC_CURVE_SIGNATURE_ALGOS(); } - virtual KeyInfo signKeyRef() const; - Signature signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, + virtual KeyInfo signKeyRef(const pcsc_cpp::SmartCard::Session& session) const; + Signature signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const override; - PinRetriesRemainingAndMax pinRetriesLeft(byte_type pinReference) const; + static PinRetriesRemainingAndMax pinRetriesLeft(const pcsc_cpp::SmartCard::Session& session, + byte_type pinReference); - void selectMain() const; - void selectADF1() const; - void selectADF2() const; + static void selectMain(const pcsc_cpp::SmartCard::Session& session); + static void selectADF1(const pcsc_cpp::SmartCard::Session& session); + static void selectADF2(const pcsc_cpp::SmartCard::Session& session); }; } // namespace electronic_id diff --git a/src/electronic-ids/pcsc/FinEID.cpp b/src/electronic-ids/pcsc/FinEID.cpp index ce2f70e..dcc6edf 100644 --- a/src/electronic-ids/pcsc/FinEID.cpp +++ b/src/electronic-ids/pcsc/FinEID.cpp @@ -61,22 +61,25 @@ constexpr byte_type RSA_PSS_ALGO = 0x05; namespace electronic_id { -byte_vector FinEIDv3::getCertificateImpl(const CertificateType type) const +byte_vector FinEIDv3::getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const { - transmitApduWithExpectedResponse(*card, SELECT_MAIN_AID); - return readFile(*card, + transmitApduWithExpectedResponse(session, SELECT_MAIN_AID); + return readFile(session, type.isAuthentication() ? SELECT_AUTH_CERT_FILE : SELECT_SIGN_CERT_FILE_V3); } -byte_vector FinEIDv3::signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const +byte_vector FinEIDv3::signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, + byte_vector&& pin, const byte_vector& hash) const { - return sign(authSignatureAlgorithm().hashAlgorithm(), hash, std::move(pin), AUTH_PIN_REFERENCE, - authPinMinMaxLength(), AUTH_KEY_REFERENCE, RSA_PSS_ALGO, 0x00); + return sign(session, authSignatureAlgorithm().hashAlgorithm(), hash, std::move(pin), + AUTH_PIN_REFERENCE, authPinMinMaxLength(), AUTH_KEY_REFERENCE, RSA_PSS_ALGO, 0x00); } -ElectronicID::PinRetriesRemainingAndMax FinEIDv3::authPinRetriesLeftImpl() const +ElectronicID::PinRetriesRemainingAndMax +FinEIDv3::authPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const { - return pinRetriesLeft(AUTH_PIN_REFERENCE); + return pinRetriesLeft(session, AUTH_PIN_REFERENCE); } const std::set& FinEIDv3::supportedSigningAlgorithms() const @@ -84,20 +87,23 @@ const std::set& FinEIDv3::supportedSigningAlgorithms() const return ELLIPTIC_CURVE_SIGNATURE_ALGOS(); } -ElectronicID::Signature FinEIDv3::signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, - const HashAlgorithm hashAlgo) const +ElectronicID::Signature +FinEIDv3::signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const { - return {sign(hashAlgo, hash, std::move(pin), SIGNING_PIN_REFERENCE, signingPinMinMaxLength(), - SIGNING_KEY_REFERENCE_V3, ECDSA_ALGO, 0x40), + return {sign(session, hashAlgo, hash, std::move(pin), SIGNING_PIN_REFERENCE, + signingPinMinMaxLength(), SIGNING_KEY_REFERENCE_V3, ECDSA_ALGO, 0x40), {SignatureAlgorithm::ES, hashAlgo}}; } -ElectronicID::PinRetriesRemainingAndMax FinEIDv3::signingPinRetriesLeftImpl() const +ElectronicID::PinRetriesRemainingAndMax +FinEIDv3::signingPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const { - return pinRetriesLeft(SIGNING_PIN_REFERENCE); + return pinRetriesLeft(session, SIGNING_PIN_REFERENCE); } -byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash, byte_vector&& pin, +byte_vector FinEIDv3::sign(const pcsc_cpp::SmartCard::Session& session, + const HashAlgorithm hashAlgo, const byte_vector& hash, byte_vector&& pin, byte_type pinReference, PinMinMaxLength pinMinMaxLength, byte_type keyReference, byte_type signatureAlgo, byte_type LE) const { @@ -127,16 +133,16 @@ byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash THROW(ArgumentFatalError, "No OID for algorithm " + std::string(hashAlgo)); } - verifyPin(*card, pinReference, std::move(pin), pinMinMaxLength.first, pinMinMaxLength.second, + verifyPin(session, pinReference, std::move(pin), pinMinMaxLength.first, pinMinMaxLength.second, PIN_PADDING_CHAR); // Select security environment for COMPUTE SIGNATURE. - selectSecurityEnv(*card, 0xB6, signatureAlgo, keyReference, name()); + selectSecurityEnv(session, 0xB6, signatureAlgo, keyReference, name()); byte_vector tlv {0x90, byte_type(hash.size())}; tlv.insert(tlv.cend(), hash.cbegin(), hash.cend()); const CommandApdu computeSignature {0x00, 0x2A, 0x90, 0xA0, std::move(tlv)}; - const auto response = card->transmit(computeSignature); + const auto response = session.transmit(computeSignature); if (response.sw1 == ResponseApdu::WRONG_LENGTH) { THROW(SmartCardError, @@ -147,7 +153,7 @@ byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash } const CommandApdu getSignature {0x00, 0x2A, 0x9E, 0x9A, LE}; - const auto signature = card->transmit(getSignature); + const auto signature = session.transmit(getSignature); if (signature.sw1 == ResponseApdu::WRONG_LENGTH) { THROW(SmartCardError, "Wrong data length in command GET SIGNATURE argument: " + response); @@ -159,12 +165,13 @@ byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash return signature.data; } -ElectronicID::PinRetriesRemainingAndMax FinEIDv3::pinRetriesLeft(byte_type pinReference) const +ElectronicID::PinRetriesRemainingAndMax +FinEIDv3::pinRetriesLeft(const pcsc_cpp::SmartCard::Session& session, byte_type pinReference) const { const auto GET_DATA = smartcard().protocol() == SmartCard::Protocol::T1 ? CommandApdu {0x00, 0xCB, 0x00, 0xFF, {0xA0, 0x03, 0x83, 0x01, pinReference}, 0x00} : CommandApdu {0x00, 0xCB, 0x00, 0xFF, {0xA0, 0x03, 0x83, 0x01, pinReference}}; - const auto response = card->transmit(GET_DATA); + const auto response = session.transmit(GET_DATA); if (!response.isOK()) { THROW(SmartCardError, "Command GET DATA failed with error " + response); } @@ -176,24 +183,27 @@ ElectronicID::PinRetriesRemainingAndMax FinEIDv3::pinRetriesLeft(byte_type pinRe return {uint8_t(response.data[20]), int8_t(5)}; } -byte_vector FinEIDv4::getCertificateImpl(const CertificateType type) const +byte_vector FinEIDv4::getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const { - transmitApduWithExpectedResponse(*card, SELECT_MAIN_AID); - return readFile(*card, + transmitApduWithExpectedResponse(session, SELECT_MAIN_AID); + return readFile(session, type.isAuthentication() ? SELECT_AUTH_CERT_FILE : SELECT_SIGN_CERT_FILE_V4); } -byte_vector FinEIDv4::signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const +byte_vector FinEIDv4::signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, + byte_vector&& pin, const byte_vector& hash) const { - return sign(authSignatureAlgorithm().hashAlgorithm(), hash, std::move(pin), AUTH_PIN_REFERENCE, - authPinMinMaxLength(), AUTH_KEY_REFERENCE, ECDSA_ALGO, 0x60); + return sign(session, authSignatureAlgorithm().hashAlgorithm(), hash, std::move(pin), + AUTH_PIN_REFERENCE, authPinMinMaxLength(), AUTH_KEY_REFERENCE, ECDSA_ALGO, 0x60); } -ElectronicID::Signature FinEIDv4::signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, - const HashAlgorithm hashAlgo) const +ElectronicID::Signature +FinEIDv4::signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const { - return {sign(hashAlgo, hash, std::move(pin), SIGNING_PIN_REFERENCE, signingPinMinMaxLength(), - SIGNING_KEY_REFERENCE_V4, ECDSA_ALGO, 0x60), + return {sign(session, hashAlgo, hash, std::move(pin), SIGNING_PIN_REFERENCE, + signingPinMinMaxLength(), SIGNING_KEY_REFERENCE_V4, ECDSA_ALGO, 0x60), {SignatureAlgorithm::ES, hashAlgo}}; } diff --git a/src/electronic-ids/pcsc/FinEID.hpp b/src/electronic-ids/pcsc/FinEID.hpp index a532768..583a85a 100644 --- a/src/electronic-ids/pcsc/FinEID.hpp +++ b/src/electronic-ids/pcsc/FinEID.hpp @@ -30,41 +30,48 @@ namespace electronic_id class FinEIDv3 : public PcscElectronicID { public: - FinEIDv3(pcsc_cpp::SmartCard::ptr _card) : PcscElectronicID(std::move(_card)) {} + using PcscElectronicID::PcscElectronicID; protected: - byte_vector getCertificateImpl(const CertificateType type) const override; + byte_vector getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const override; JsonWebSignatureAlgorithm authSignatureAlgorithm() const override { return JsonWebSignatureAlgorithm::PS256; } PinMinMaxLength authPinMinMaxLength() const override { return {4, 12}; } - PinRetriesRemainingAndMax authPinRetriesLeftImpl() const override; + PinRetriesRemainingAndMax + authPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const override; const std::set& supportedSigningAlgorithms() const override; PinMinMaxLength signingPinMinMaxLength() const override { return {6, 12}; } - PinRetriesRemainingAndMax signingPinRetriesLeftImpl() const override; + PinRetriesRemainingAndMax + signingPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const override; std::string name() const override { return "FinEID v3"; } Type type() const override { return FinEID; } - byte_vector signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const override; + byte_vector signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash) const override; - Signature signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, + Signature signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const override; - byte_vector sign(const HashAlgorithm hashAlgo, const byte_vector& hash, byte_vector&& pin, - byte_type pinReference, PinMinMaxLength pinMinMaxLength, - byte_type keyReference, byte_type signatureAlgo, byte_type LE) const; + byte_vector sign(const pcsc_cpp::SmartCard::Session& session, const HashAlgorithm hashAlgo, + const byte_vector& hash, byte_vector&& pin, byte_type pinReference, + PinMinMaxLength pinMinMaxLength, byte_type keyReference, + byte_type signatureAlgo, byte_type LE) const; - PinRetriesRemainingAndMax pinRetriesLeft(byte_type pinReference) const; + PinRetriesRemainingAndMax pinRetriesLeft(const pcsc_cpp::SmartCard::Session& session, + byte_type pinReference) const; }; class FinEIDv4 : public FinEIDv3 { public: - FinEIDv4(pcsc_cpp::SmartCard::ptr _card) : FinEIDv3(std::move(_card)) {} + using FinEIDv3::FinEIDv3; private: JsonWebSignatureAlgorithm authSignatureAlgorithm() const override @@ -72,13 +79,16 @@ class FinEIDv4 : public FinEIDv3 return JsonWebSignatureAlgorithm::ES384; } - byte_vector getCertificateImpl(const CertificateType type) const override; + byte_vector getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const override; std::string name() const override { return "FinEID v4"; } - byte_vector signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const override; + byte_vector signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash) const override; - Signature signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, + Signature signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, byte_vector&& pin, + const byte_vector& hash, const HashAlgorithm hashAlgo) const override; }; diff --git a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.cpp b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.cpp index 6e2442f..9d60c99 100644 --- a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.cpp +++ b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.cpp @@ -49,21 +49,22 @@ constexpr byte_type CERT_FILE_REF = 0xA4; } // namespace -LatEIDIDEMIAV2::LatEIDIDEMIAV2(pcsc_cpp::SmartCard::ptr _card) : +LatEIDIDEMIAV2::LatEIDIDEMIAV2(SmartCard&& _card) : EIDIDEMIA(std::move(_card)), data(std::make_unique()) { } LatEIDIDEMIAV2::~LatEIDIDEMIAV2() = default; -byte_vector LatEIDIDEMIAV2::getCertificateImpl(const CertificateType type) const +byte_vector LatEIDIDEMIAV2::getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const { - selectMain(); - type.isAuthentication() ? selectADF1() : selectADF2(); - auto info = - readDCODInfo(CERT_FILE_REF, type.isAuthentication() ? data->authCache : data->signCache); + selectMain(session); + type.isAuthentication() ? selectADF1(session) : selectADF2(session); + auto info = readDCODInfo(session, CERT_FILE_REF, + type.isAuthentication() ? data->authCache : data->signCache); if (TLV id = TLV::path(info, 0x30, 0xA1, 0x30, 0x30, 0x04)) { - return readFile(*card, CommandApdu::selectEF(0x02, {id.begin, id.end})); + return readFile(session, CommandApdu::selectEF(0x02, {id.begin, id.end})); } THROW(SmartCardError, "EF.CD reference not found"); } @@ -71,9 +72,9 @@ byte_vector LatEIDIDEMIAV2::getCertificateImpl(const CertificateType type) const JsonWebSignatureAlgorithm LatEIDIDEMIAV2::authSignatureAlgorithm() const { if (!data->authKeyInfo.has_value()) { - auto transactionGuard = card->beginTransaction(); - selectADF1(); - authKeyRef(); + auto session = card.beginSession(); + selectADF1(session); + authKeyRef(session); } return data->authKeyInfo->isECC ? JsonWebSignatureAlgorithm::ES384 : JsonWebSignatureAlgorithm::RS256; @@ -82,9 +83,9 @@ JsonWebSignatureAlgorithm LatEIDIDEMIAV2::authSignatureAlgorithm() const const std::set& LatEIDIDEMIAV2::supportedSigningAlgorithms() const { if (!data->signKeyInfo.has_value()) { - auto transactionGuard = card->beginTransaction(); - selectADF2(); - signKeyRef(); + auto session = card.beginSession(); + selectADF2(session); + signKeyRef(session); } const static std::set RS256_SIGNATURE_ALGO { {SignatureAlgorithm::RS256}, @@ -92,50 +93,54 @@ const std::set& LatEIDIDEMIAV2::supportedSigningAlgorithms() return data->signKeyInfo->isECC ? ELLIPTIC_CURVE_SIGNATURE_ALGOS() : RS256_SIGNATURE_ALGO; } -EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::authKeyRef() const +EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::authKeyRef(const pcsc_cpp::SmartCard::Session& session) const { if (!data->authKeyInfo.has_value()) { - data->authKeyInfo = readPrKDInfo(EIDIDEMIA::authKeyRef().id, data->authCache); + data->authKeyInfo = + readPrKDInfo(session, EIDIDEMIA::authKeyRef(session).id, data->authCache); } return data->authKeyInfo.value(); } -EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::signKeyRef() const +EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::signKeyRef(const pcsc_cpp::SmartCard::Session& session) const { if (!data->signKeyInfo.has_value()) { - data->signKeyInfo = readPrKDInfo(EIDIDEMIA::signKeyRef().id, data->signCache); + data->signKeyInfo = + readPrKDInfo(session, EIDIDEMIA::signKeyRef(session).id, data->signCache); } return data->signKeyInfo.value(); } template -TLV LatEIDIDEMIAV2::readEF_File(byte_vector file, C& cache) const +TLV LatEIDIDEMIAV2::readEF_File(const SmartCard::Session& session, byte_vector file, C& cache) const { if (auto it = cache.find(file); it != cache.end()) { return TLV(it->second); } - return TLV(cache[std::move(file)] = readFile(*card, CommandApdu::selectEF(0x02, file))); + return TLV(cache[std::move(file)] = readFile(session, CommandApdu::selectEF(0x02, file))); } template -TLV LatEIDIDEMIAV2::readDCODInfo(byte_type type, C& cache) const +TLV LatEIDIDEMIAV2::readDCODInfo(const pcsc_cpp::SmartCard::Session& session, byte_type type, + C& cache) const { - const auto info = readEF_File(EF_OD, cache); + const auto info = readEF_File(session, EF_OD, cache); for (TLV ref(info); ref; ++ref) { if (ref.tag != type) { continue; } if (auto file = ref[0x30][0x04]; file && file.length == 2) { - return readEF_File({file.begin, file.end}, cache); + return readEF_File(session, {file.begin, file.end}, cache); } } THROW(SmartCardError, "EF.DCOD reference not found"); } template -EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::readPrKDInfo(byte_type keyID, C& cache) const +EIDIDEMIA::KeyInfo LatEIDIDEMIAV2::readPrKDInfo(const pcsc_cpp::SmartCard::Session& session, + byte_type keyID, C& cache) const { - TLV prKD = readDCODInfo(PRIV_FILE_REF, cache); + TLV prKD = readDCODInfo(session, PRIV_FILE_REF, cache); if (!prKD) { THROW(SmartCardError, "EF.PrKD reference not found"); } diff --git a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp index 73ff9c2..d2b5de2 100644 --- a/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp +++ b/src/electronic-ids/pcsc/LatEIDIDEMIAv2.hpp @@ -34,12 +34,13 @@ struct TLV; class LatEIDIDEMIAV2 : public EIDIDEMIA { public: - explicit LatEIDIDEMIAV2(pcsc_cpp::SmartCard::ptr _card); + explicit LatEIDIDEMIAV2(pcsc_cpp::SmartCard&& _card); ~LatEIDIDEMIAV2() override; PCSC_CPP_DISABLE_COPY_MOVE(LatEIDIDEMIAV2); private: - byte_vector getCertificateImpl(const CertificateType type) const override; + byte_vector getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const override; JsonWebSignatureAlgorithm authSignatureAlgorithm() const override; PinMinMaxLength authPinMinMaxLength() const override { return {4, 12}; } @@ -50,15 +51,16 @@ class LatEIDIDEMIAV2 : public EIDIDEMIA std::string name() const override { return "LatEID IDEMIA v2"; } Type type() const override { return LatEID; } - KeyInfo authKeyRef() const override; - KeyInfo signKeyRef() const override; + KeyInfo authKeyRef(const pcsc_cpp::SmartCard::Session& session) const override; + KeyInfo signKeyRef(const pcsc_cpp::SmartCard::Session& session) const override; template - TLV readEF_File(byte_vector file, C& cache) const; + TLV readEF_File(const pcsc_cpp::SmartCard::Session& session, byte_vector file, C& cache) const; template - TLV readDCODInfo(byte_type type, C& cache) const; + TLV readDCODInfo(const pcsc_cpp::SmartCard::Session& session, byte_type type, C& cache) const; template - KeyInfo readPrKDInfo(byte_type keyID, C& cache) const; + KeyInfo readPrKDInfo(const pcsc_cpp::SmartCard::Session& session, byte_type keyID, + C& cache) const; struct Private; std::unique_ptr data; diff --git a/src/electronic-ids/pcsc/PcscElectronicID.hpp b/src/electronic-ids/pcsc/PcscElectronicID.hpp index a8876b2..05868a9 100644 --- a/src/electronic-ids/pcsc/PcscElectronicID.hpp +++ b/src/electronic-ids/pcsc/PcscElectronicID.hpp @@ -32,42 +32,35 @@ namespace electronic_id class PcscElectronicID : public ElectronicID { public: - PcscElectronicID(pcsc_cpp::SmartCard::ptr _card) : ElectronicID(std::move(_card)) {} + explicit PcscElectronicID(pcsc_cpp::SmartCard&& _card) : ElectronicID(std::move(_card)) {} protected: byte_vector getCertificate(const CertificateType type) const override { - auto transactionGuard = card->beginTransaction(); - return getCertificateImpl(type); + return getCertificateImpl(card.beginSession(), type); } byte_vector signWithAuthKey(byte_vector&& pin, const byte_vector& hash) const override { validateAuthHashLength(authSignatureAlgorithm(), name(), hash); - - auto transactionGuard = card->beginTransaction(); - return signWithAuthKeyImpl(std::move(pin), hash); + return signWithAuthKeyImpl(card.beginSession(), std::move(pin), hash); } Signature signWithSigningKey(byte_vector&& pin, const byte_vector& hash, const HashAlgorithm hashAlgo) const override { validateSigningHash(*this, hashAlgo, hash); - - auto transactionGuard = card->beginTransaction(); - return signWithSigningKeyImpl(std::move(pin), hash, hashAlgo); + return signWithSigningKeyImpl(card.beginSession(), std::move(pin), hash, hashAlgo); } PinRetriesRemainingAndMax signingPinRetriesLeft() const override { - auto transactionGuard = card->beginTransaction(); - return signingPinRetriesLeftImpl(); + return signingPinRetriesLeftImpl(card.beginSession()); } ElectronicID::PinRetriesRemainingAndMax authPinRetriesLeft() const override { - auto transactionGuard = card->beginTransaction(); - return authPinRetriesLeftImpl(); + return authPinRetriesLeftImpl(card.beginSession()); } // The following pure virtual *Impl functions are the interface of all @@ -75,16 +68,21 @@ class PcscElectronicID : public ElectronicID // they have to be implemented when adding a new electronic ID. // This design follows the non-virtual interface pattern. - virtual byte_vector getCertificateImpl(const CertificateType type) const = 0; + virtual byte_vector getCertificateImpl(const pcsc_cpp::SmartCard::Session& session, + const CertificateType type) const = 0; - virtual byte_vector signWithAuthKeyImpl(byte_vector&& pin, const byte_vector& hash) const = 0; + virtual byte_vector signWithAuthKeyImpl(const pcsc_cpp::SmartCard::Session& session, + byte_vector&& pin, const byte_vector& hash) const = 0; - virtual PinRetriesRemainingAndMax authPinRetriesLeftImpl() const = 0; + virtual PinRetriesRemainingAndMax + authPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const = 0; - virtual Signature signWithSigningKeyImpl(byte_vector&& pin, const byte_vector& hash, + virtual Signature signWithSigningKeyImpl(const pcsc_cpp::SmartCard::Session& session, + byte_vector&& pin, const byte_vector& hash, const HashAlgorithm hashAlgo) const = 0; - virtual PinRetriesRemainingAndMax signingPinRetriesLeftImpl() const = 0; + virtual PinRetriesRemainingAndMax + signingPinRetriesLeftImpl(const pcsc_cpp::SmartCard::Session& session) const = 0; }; } // namespace electronic_id diff --git a/src/electronic-ids/pcsc/pcsc-common.hpp b/src/electronic-ids/pcsc/pcsc-common.hpp index d47b9ed..d0eb650 100644 --- a/src/electronic-ids/pcsc/pcsc-common.hpp +++ b/src/electronic-ids/pcsc/pcsc-common.hpp @@ -32,11 +32,11 @@ namespace electronic_id { -inline pcsc_cpp::byte_vector readFile(pcsc_cpp::SmartCard& card, +inline pcsc_cpp::byte_vector readFile(const pcsc_cpp::SmartCard::Session& session, const pcsc_cpp::CommandApdu& select, pcsc_cpp::byte_type blockLength = 0x00) { - auto response = card.transmit(select); + auto response = session.transmit(select); if (!response.isOK()) { THROW(SmartCardError, "Failed to select EF file"); } @@ -51,7 +51,8 @@ inline pcsc_cpp::byte_vector readFile(pcsc_cpp::SmartCard& card, if (size.length != 2) { THROW(SmartCardError, "Failed to read EF file length"); } - return pcsc_cpp::readBinary(card, pcsc_cpp::toSW(*size.begin, *(size.begin + 1)), blockLength); + return pcsc_cpp::readBinary(session, pcsc_cpp::toSW(*size.begin, *(size.begin + 1)), + blockLength); } PCSC_CPP_CONSTEXPR_VECTOR inline pcsc_cpp::byte_vector @@ -67,22 +68,22 @@ addPaddingToPin(pcsc_cpp::byte_vector&& pin, size_t paddingLength, pcsc_cpp::byt return std::move(pin); } -inline void verifyPin(pcsc_cpp::SmartCard& card, pcsc_cpp::byte_type p2, +inline void verifyPin(const pcsc_cpp::SmartCard::Session& session, pcsc_cpp::byte_type p2, pcsc_cpp::byte_vector&& pin, uint8_t pinMinLength, size_t paddingLength, pcsc_cpp::byte_type paddingChar) { pcsc_cpp::ResponseApdu response; - if (card.readerHasPinPad()) { + if (session.readerHasPinPad()) { const pcsc_cpp::CommandApdu verifyPin {0x00, 0x20, 0x00, p2, pcsc_cpp::byte_vector(paddingLength, paddingChar)}; - response = card.transmitCTL(verifyPin, 0, pinMinLength); + response = session.transmitCTL(verifyPin, 0, pinMinLength); } else { const pcsc_cpp::CommandApdu verifyPin { 0x00, 0x20, 0x00, p2, addPaddingToPin(std::move(pin), paddingLength, paddingChar)}; - response = card.transmit(verifyPin); + response = session.transmit(verifyPin); } // NOTE: in case card-specific error handling logic is needed, @@ -126,12 +127,12 @@ inline void verifyPin(pcsc_cpp::SmartCard& card, pcsc_cpp::byte_type p2, } } -inline pcsc_cpp::byte_vector internalAuthenticate(pcsc_cpp::SmartCard& card, +inline pcsc_cpp::byte_vector internalAuthenticate(const pcsc_cpp::SmartCard::Session& session, const pcsc_cpp::byte_vector& hash, const std::string& cardType) { pcsc_cpp::CommandApdu internalAuth {0x00, 0x88, 0x00, 0x00, hash, 0}; - const auto response = card.transmit(internalAuth); + const auto response = session.transmit(internalAuth); if (response.sw1 == pcsc_cpp::ResponseApdu::WRONG_LENGTH) { THROW(SmartCardError, @@ -146,12 +147,12 @@ inline pcsc_cpp::byte_vector internalAuthenticate(pcsc_cpp::SmartCard& card, return response.data; } -inline pcsc_cpp::byte_vector computeSignature(pcsc_cpp::SmartCard& card, +inline pcsc_cpp::byte_vector computeSignature(const pcsc_cpp::SmartCard::Session& session, const pcsc_cpp::byte_vector& hash, const std::string& cardType) { pcsc_cpp::CommandApdu computeSignature {0x00, 0x2A, 0x9E, 0x9A, hash, 0}; - const auto response = card.transmit(computeSignature); + const auto response = session.transmit(computeSignature); if (response.sw1 == pcsc_cpp::ResponseApdu::WRONG_LENGTH) { THROW(SmartCardError, @@ -165,12 +166,13 @@ inline pcsc_cpp::byte_vector computeSignature(pcsc_cpp::SmartCard& card, return response.data; } -inline pcsc_cpp::byte_type selectSecurityEnv(pcsc_cpp::SmartCard& card, pcsc_cpp::byte_type env, +inline pcsc_cpp::byte_type selectSecurityEnv(const pcsc_cpp::SmartCard::Session& session, + pcsc_cpp::byte_type env, pcsc_cpp::byte_type signatureAlgo, pcsc_cpp::byte_type keyReference, const std::string& cardType) { - const auto response = card.transmit( + const auto response = session.transmit( {0x00, 0x22, 0x41, env, {0x80, 0x01, signatureAlgo, 0x84, 0x01, keyReference}}); if (!response.isOK()) { diff --git a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp index a30d4d4..6d02841 100644 --- a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp +++ b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp @@ -218,8 +218,7 @@ const Pkcs11ElectronicIDModule& getModule(ElectronicID::Type eidType) } // namespace Pkcs11ElectronicID::Pkcs11ElectronicID(ElectronicID::Type type) : - ElectronicID {std::make_unique()}, module {getModule(type)}, - manager {PKCS11CardManager::instance(module.path)} + ElectronicID {{}}, module {getModule(type)}, manager {PKCS11CardManager::instance(module.path)} { REQUIRE_NON_NULL(manager)