diff --git a/include/electronic-id/enums.hpp b/include/electronic-id/enums.hpp index be6e21c..cb58b6f 100644 --- a/include/electronic-id/enums.hpp +++ b/include/electronic-id/enums.hpp @@ -144,7 +144,7 @@ class SignatureAlgorithm constexpr bool operator==(HashAlgorithm other) const { - return other.operator ==(operator HashAlgorithm()); + return other.operator==(operator HashAlgorithm()); } constexpr bool operator==(SignatureAlgorithmEnum other) const { return value == other; } diff --git a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp index 1901bae..f05c241 100644 --- a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp +++ b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp @@ -84,7 +84,7 @@ constexpr uint16_t toSW(byte_type sw1, byte_type sw2) noexcept /** Struct that wraps response APDUs. */ struct ResponseApdu { - enum Status: byte_type { + enum Status : byte_type { OK = 0x90, MORE_DATA_AVAILABLE = 0x61, VERIFICATION_FAILED = 0x63, @@ -141,52 +141,41 @@ struct ResponseApdu /** Struct that wraps command APDUs. */ struct CommandApdu { - byte_type cla; - byte_type ins; - byte_type p1; - byte_type p2; - unsigned short le; - // Lc is data.size() - byte_vector data; - - static const size_t MAX_DATA_SIZE = 255; - static const unsigned short LE_UNUSED = std::numeric_limits::max(); - - CommandApdu(byte_type c, byte_type i, byte_type pp1, byte_type pp2, byte_vector d = {}, - unsigned short l = LE_UNUSED) : - cla(c), ins(i), p1(pp1), p2(pp2), le(l), data(std::move(d)) + static constexpr size_t MAX_DATA_SIZE = 255; + + // Case 1 + PCSC_CPP_CONSTEXPR_VECTOR CommandApdu(byte_type cls, byte_type ins, byte_type p1, + byte_type p2) : d {cls, ins, p1, p2} { } - CommandApdu(const CommandApdu& other, byte_vector d) : - CommandApdu(other.cla, other.ins, other.p1, other.p2, std::move(d), other.le) + // Case 2 + PCSC_CPP_CONSTEXPR_VECTOR CommandApdu(byte_type cls, byte_type ins, byte_type p1, byte_type p2, + byte_type le) : d {cls, ins, p1, p2, le} { } - constexpr bool isLeSet() const noexcept { return le != LE_UNUSED; } - - byte_vector toBytes() const + // Case 3 + PCSC_CPP_CONSTEXPR_VECTOR CommandApdu(byte_type cls, byte_type ins, byte_type p1, byte_type p2, + byte_vector data) : d {std::move(data)} { - if (data.size() > MAX_DATA_SIZE) { - throw std::invalid_argument("Command chaining not supported"); + if (d.size() > MAX_DATA_SIZE) { + throw std::invalid_argument("Command chaining and extended lenght not supported"); } + d.insert(d.begin(), {cls, ins, p1, p2, static_cast(d.size())}); + } - auto bytes = byte_vector {cla, ins, p1, p2}; - - if (!data.empty()) { - bytes.push_back(static_cast(data.size())); - bytes.insert(bytes.end(), data.cbegin(), data.cend()); - } + // Case 4 + PCSC_CPP_CONSTEXPR_VECTOR CommandApdu(byte_type cls, byte_type ins, byte_type p1, byte_type p2, + byte_vector data, byte_type le) : + CommandApdu {cls, ins, p1, p2, std::move(data)} + { + d.push_back(le); + } - if (isLeSet()) { - // TODO: EstEID spec: the maximum value of Le is 0xFE - if (le > ResponseApdu::MAX_DATA_SIZE) - throw std::invalid_argument("LE larger than response size"); - bytes.push_back(static_cast(le)); - } + constexpr operator const byte_vector&() const { return d; } - return bytes; - } + byte_vector d; }; /** Opaque class that wraps the PC/SC smart card resources like card handle and I/O protocol. */ @@ -291,7 +280,7 @@ void transmitApduWithExpectedResponse(const SmartCard& card, const CommandApdu& size_t readDataLengthFromAsn1(const SmartCard& card); /** Read lenght bytes from currently selected binary file in blockLength-sized chunks. */ -byte_vector readBinary(const SmartCard& card, const size_t length, const size_t blockLength); +byte_vector readBinary(const SmartCard& card, const size_t length, byte_type blockLength); // Errors. diff --git a/lib/libpcsc-cpp/src/SmartCard.cpp b/lib/libpcsc-cpp/src/SmartCard.cpp index 5661f45..005662b 100644 --- a/lib/libpcsc-cpp/src/SmartCard.cpp +++ b/lib/libpcsc-cpp/src/SmartCard.cpp @@ -317,7 +317,7 @@ ResponseApdu SmartCard::transmit(const CommandApdu& command) const THROW(std::logic_error, "Call SmartCard::transmit() inside a transaction"); } - return card->transmitBytes(command.toBytes()); + return card->transmitBytes(command); } ResponseApdu SmartCard::transmitCTL(const CommandApdu& command, uint16_t lang, uint8_t minlen) const @@ -327,7 +327,7 @@ ResponseApdu SmartCard::transmitCTL(const CommandApdu& command, uint16_t lang, u THROW(std::logic_error, "Call SmartCard::transmit() inside a transaction"); } - return card->transmitBytesCTL(command.toBytes(), lang, minlen); + return card->transmitBytesCTL(command, lang, minlen); } } // namespace pcsc_cpp diff --git a/lib/libpcsc-cpp/src/utils.cpp b/lib/libpcsc-cpp/src/utils.cpp index 0822cca..f6214e6 100644 --- a/lib/libpcsc-cpp/src/utils.cpp +++ b/lib/libpcsc-cpp/src/utils.cpp @@ -58,8 +58,8 @@ class UnexpectedResponseError : public Error const char* file, const int line, const char* callerFunctionName) : Error("transmitApduWithExpectedResponse(): Unexpected response to command '"s - + bytes2hexstr(command.toBytes()) + "' - expected '9000', got '"s - + bytes2hexstr(response.toBytes()) + " in " + removeAbsolutePathPrefix(file) + ':' + + bytes2hexstr(command) + "' - expected '9000', got '"s + + bytes2hexstr(response.toBytes()) + "' in " + removeAbsolutePathPrefix(file) + ':' + std::to_string(line) + ':' + callerFunctionName) { } @@ -95,7 +95,7 @@ size_t readDataLengthFromAsn1(const SmartCard& card) // p1 - offset size first byte, 0 // p2 - offset size second byte, 0 // le - number of bytes to read, need 4 bytes from start for length - const auto readBinary4Bytes = CommandApdu {0x00, 0xb0, 0x00, 0x00, byte_vector(), 0x04}; + const CommandApdu readBinary4Bytes {0x00, 0xb0, 0x00, 0x00, 0x04}; auto response = card.transmit(readBinary4Bytes); @@ -129,24 +129,19 @@ size_t readDataLengthFromAsn1(const SmartCard& card) return length; } -byte_vector readBinary(const SmartCard& card, const size_t length, const size_t blockLength) +byte_vector readBinary(const SmartCard& card, const size_t length, byte_type blockLength) { - size_t blockLengthVar = blockLength; auto lengthCounter = length; auto resultBytes = byte_vector {}; - auto readBinary = CommandApdu {0x00, 0xb0, 0x00, 0x00}; for (size_t offset = 0; lengthCounter != 0; - offset += blockLengthVar, lengthCounter -= blockLengthVar) { + offset += blockLength, lengthCounter -= blockLength) { - if (blockLengthVar > lengthCounter) { - blockLengthVar = lengthCounter; + if (blockLength > lengthCounter) { + blockLength = byte_type(lengthCounter); } - readBinary.p1 = HIBYTE(offset); - readBinary.p2 = LOBYTE(offset); - readBinary.le = static_cast(blockLengthVar); - + CommandApdu readBinary {0x00, 0xb0, HIBYTE(offset), LOBYTE(offset), blockLength}; auto response = card.transmit(readBinary); resultBytes.insert(resultBytes.end(), response.data.cbegin(), response.data.cend()); diff --git a/src/electronic-ids/pcsc/FinEID.cpp b/src/electronic-ids/pcsc/FinEID.cpp index b70c29c..464dcb9 100644 --- a/src/electronic-ids/pcsc/FinEID.cpp +++ b/src/electronic-ids/pcsc/FinEID.cpp @@ -143,7 +143,7 @@ byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash 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 CommandApdu computeSignature {0x00, 0x2A, 0x90, 0xA0, std::move(tlv)}; const auto response = card->transmit(computeSignature); if (response.sw1 == ResponseApdu::WRONG_LENGTH) { @@ -156,7 +156,7 @@ byte_vector FinEIDv3::sign(const HashAlgorithm hashAlgo, const byte_vector& hash "Command COMPUTE SIGNATURE failed with error " + bytes2hexstr(response.toBytes())); } - const CommandApdu getSignature {0x00, 0x2A, 0x9E, 0x9A, {}, LE}; + const CommandApdu getSignature {0x00, 0x2A, 0x9E, 0x9A, LE}; const auto signature = card->transmit(getSignature); if (signature.sw1 == ResponseApdu::WRONG_LENGTH) { diff --git a/src/electronic-ids/pcsc/pcsc-common.hpp b/src/electronic-ids/pcsc/pcsc-common.hpp index b72b9ae..bf6e2ae 100644 --- a/src/electronic-ids/pcsc/pcsc-common.hpp +++ b/src/electronic-ids/pcsc/pcsc-common.hpp @@ -34,7 +34,7 @@ namespace electronic_id inline pcsc_cpp::byte_vector getCertificate(pcsc_cpp::SmartCard& card, const pcsc_cpp::CommandApdu& selectCertFileCmd) { - static const size_t MAX_LE_VALUE = 0xb5; + static const pcsc_cpp::byte_type MAX_LE_VALUE = 0xb5; transmitApduWithExpectedResponse(card, selectCertFileCmd); @@ -43,28 +43,27 @@ inline pcsc_cpp::byte_vector getCertificate(pcsc_cpp::SmartCard& card, return readBinary(card, length, MAX_LE_VALUE); } -inline pcsc_cpp::byte_vector addPaddingToPin(pcsc_cpp::byte_vector&& pin, size_t paddingLength, - pcsc_cpp::byte_type paddingChar) +PCSC_CPP_CONSTEXPR_VECTOR inline pcsc_cpp::byte_vector +addPaddingToPin(pcsc_cpp::byte_vector&& pin, size_t paddingLength, pcsc_cpp::byte_type paddingChar) { pin.resize(std::max(pin.size(), paddingLength), paddingChar); - return pin; + return std::move(pin); } inline void verifyPin(pcsc_cpp::SmartCard& card, pcsc_cpp::byte_type p2, pcsc_cpp::byte_vector&& pin, uint8_t pinMinLength, size_t paddingLength, pcsc_cpp::byte_type paddingChar) { - const pcsc_cpp::CommandApdu VERIFY_PIN {0x00, 0x20, 0x00, p2}; pcsc_cpp::ResponseApdu response; if (card.readerHasPinPad()) { - const pcsc_cpp::CommandApdu verifyPin {VERIFY_PIN, + const pcsc_cpp::CommandApdu verifyPin {0x00, 0x20, 0x00, p2, addPaddingToPin({}, paddingLength, paddingChar)}; response = card.transmitCTL(verifyPin, 0, pinMinLength); } else { const pcsc_cpp::CommandApdu verifyPin { - VERIFY_PIN, addPaddingToPin(std::move(pin), paddingLength, paddingChar)}; + 0x00, 0x20, 0x00, p2, addPaddingToPin(std::move(pin), paddingLength, paddingChar)}; response = card.transmit(verifyPin); } @@ -119,15 +118,7 @@ inline pcsc_cpp::byte_vector internalAuthenticate(pcsc_cpp::SmartCard& card, const pcsc_cpp::byte_vector& hash, const std::string& cardType) { - static const pcsc_cpp::CommandApdu INTERNAL_AUTHENTICATE {0x00, 0x88, 0x00, 0x00}; - - pcsc_cpp::CommandApdu internalAuth {INTERNAL_AUTHENTICATE, hash}; - // LE is needed in case of protocol T1. - // TODO: Implement this in libpcsc-cpp. - if (card.protocol() == pcsc_cpp::SmartCard::Protocol::T1) { - internalAuth.le = 0; - } - + pcsc_cpp::CommandApdu internalAuth {0x00, 0x88, 0x00, 0x00, hash, 0}; const auto response = card.transmit(internalAuth); if (response.sw1 == pcsc_cpp::ResponseApdu::WRONG_LENGTH) { @@ -148,15 +139,7 @@ inline pcsc_cpp::byte_vector computeSignature(pcsc_cpp::SmartCard& card, const pcsc_cpp::byte_vector& hash, const std::string& cardType) { - static const pcsc_cpp::CommandApdu COMPUTE_SIGNATURE {0x00, 0x2A, 0x9E, 0x9A}; - - pcsc_cpp::CommandApdu computeSignature {COMPUTE_SIGNATURE, hash}; - // LE is needed in case of protocol T1. - // TODO: Implement this in libpcsc-cpp. - if (card.protocol() == pcsc_cpp::SmartCard::Protocol::T1) { - computeSignature.le = 0; - } - + pcsc_cpp::CommandApdu computeSignature {0x00, 0x2A, 0x9E, 0x9A, hash, 0}; const auto response = card.transmit(computeSignature); if (response.sw1 == pcsc_cpp::ResponseApdu::WRONG_LENGTH) {