diff --git a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp index 3b34c19..a17a3c6 100644 --- a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp +++ b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp @@ -309,7 +309,7 @@ constexpr uint8_t PIN_PAD_PIN_ENTRY_TIMEOUT = 90; // 1 minute, 30 seconds class SmartCard { public: - enum class Protocol { UNDEFINED, T0, T1 }; // AUTO = T0 | T1 + enum class Protocol : uint8_t { UNDEFINED, T0, T1 }; // AUTO = T0 | T1 class Session { diff --git a/lib/libpcsc-cpp/src/SmartCard.cpp b/lib/libpcsc-cpp/src/SmartCard.cpp index c3a2aad..1534ccd 100644 --- a/lib/libpcsc-cpp/src/SmartCard.cpp +++ b/lib/libpcsc-cpp/src/SmartCard.cpp @@ -232,25 +232,7 @@ class CardImpl responseBytes.resize(responseLength - 2); PCSC_CPP_WARNING_POP - ResponseApdu response {sw1, sw2, std::move(responseBytes)}; - - // Let expected errors through for handling in upper layers or in if blocks below. - switch (response.sw1) { - using enum ResponseApdu::Status; - case OK: - case MORE_DATA_AVAILABLE: - case WRONG_LE_LENGTH: - case VERIFICATION_FAILED: - case VERIFICATION_CANCELLED: - case WRONG_LENGTH: - case COMMAND_NOT_ALLOWED: - case WRONG_PARAMETERS: - return response; - default: - THROW(Error, - "Error response: '" + response + "', protocol " - + std::to_string(_protocol.dwProtocol)); - } + return {sw1, sw2, std::move(responseBytes)}; } }; @@ -272,14 +254,34 @@ ResponseApdu SmartCard::Session::transmit(const CommandApdu& command) const if (response.sw1 == ResponseApdu::WRONG_LE_LENGTH) { response = card.transmitBytes(CommandApdu(command, response.sw2)); } - while (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) { - auto newResponse = card.transmitBytes(CommandApdu::getResponse(response.sw2)); - response.sw1 = newResponse.sw1; - response.sw2 = newResponse.sw2; - response.data.insert(response.data.end(), newResponse.data.cbegin(), - newResponse.data.cend()); + // Let expected errors through for handling in upper layers or in if blocks below. + switch (response.sw1) { + using enum ResponseApdu::Status; + case MORE_DATA_AVAILABLE: + while (response.sw1 == ResponseApdu::MORE_DATA_AVAILABLE) { + auto newResponse = transmit(CommandApdu::getResponse(response.sw2)); + response.sw1 = newResponse.sw1; + response.sw2 = newResponse.sw2; + response.data.insert(response.data.end(), newResponse.data.cbegin(), + newResponse.data.cend()); + if (response.data.size() > (std::numeric_limits::max)()) { + THROW(Error, "Command chaining and extended lenght not supported"); + } + } + return response; + case OK: + case WRONG_LE_LENGTH: + case VERIFICATION_FAILED: + case VERIFICATION_CANCELLED: + case WRONG_LENGTH: + case COMMAND_NOT_ALLOWED: + case WRONG_PARAMETERS: + return response; + default: + THROW(Error, + "Error response: '" + response + "', protocol " + + std::to_string(uint8_t(card.protocol()))); } - return response; } ResponseApdu SmartCard::Session::transmitCTL(const CommandApdu& command, uint16_t lang,