From 7306f589c94a06562d152ae0398238ae5d024bc9 Mon Sep 17 00:00:00 2001 From: Jose Vicente Campos Date: Sun, 12 Jun 2022 09:50:22 +0200 Subject: [PATCH 1/3] fixed IsoDep protocol parser and other improvements --- .../app-qt/src/main/cpp/model/StreamModel.cpp | 280 +++++++++++------- .../app-qt/src/main/cpp/parser/ParserNfc.cpp | 151 +--------- .../app-qt/src/main/cpp/parser/ParserNfc.h | 12 +- .../app-qt/src/main/cpp/parser/ParserNfcA.cpp | 4 +- 4 files changed, 190 insertions(+), 257 deletions(-) diff --git a/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp b/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp index e6f5fab1..a6fc9ea1 100644 --- a/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp +++ b/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp @@ -212,121 +212,19 @@ struct StreamModel::Impl { case nfc::TechType::NfcA: - // skip encrypted frames - if (frame->isEncrypted()) - return {}; - - if (frame->isPollFrame()) - { - int command = (*frame)[0]; - - // Protocol Parameter Selection - if (command == 0x50 && frame->limit() == 4) - return "HALT"; - - // Protocol Parameter Selection - if ((command & 0xF0) == 0xD0 && frame->limit() == 5) - return "PPS"; - - // ISO-DEP protocol I-Block - if ((command & 0xE2) == 0x02 && frame->limit() > 4) - return "I-Block"; - - // ISO-DEP protocol R-Block - if ((command & 0xE6) == 0xA2 && frame->limit() == 3) - return "R-Block"; - - // ISO-DEP protocol S-Block - if ((command & 0xC7) == 0xC2 && frame->limit() == 4) - return "S-Block"; - - if (NfcACmd.contains(command)) - return NfcACmd[command]; - } - else if (prev && prev->isPollFrame()) - { - int command = (*prev)[0]; - - if (command == 0x93 || command == 0x95 || command == 0x97) - { - if (frame->limit() == 3) - return "SAK"; - - if (frame->limit() == 5) - return "UID"; - } - - if (NfcAResp.contains(command)) - return NfcAResp[command]; - } - - return {}; + return eventNfcA(frame, prev); case nfc::TechType::NfcB: - if (frame->isPollFrame()) - { - int command = (*frame)[0]; - - // ISO-DEP protocol I-Block - if ((command & 0xE2) == 0x02 && frame->limit() > 4) - return "I-Block"; - - // ISO-DEP protocol R-Block - if ((command & 0xE6) == 0xA2 && frame->limit() == 3) - return "R-Block"; - - // ISO-DEP protocol S-Block - if ((command & 0xC7) == 0xC2 && frame->limit() == 4) - return "S-Block"; - - if (NfcBCmd.contains(command)) - return NfcBCmd[command]; - } - else if (prev && prev->isPollFrame()) - { - int command = (*prev)[0]; - - if (NfcBResp.contains(command)) - return NfcBResp[command]; - } - - return {}; + return eventNfcB(frame, prev); case nfc::TechType::NfcF: - if (frame->isPollFrame()) - { - int command = (*frame)[1]; - - if (NfcFCmd.contains(command)) - return NfcFCmd[command]; - - return QString("CMD %1").arg(command, 2, 16, QChar('0')); - } - else - { - int command = (*frame)[1]; - - if (NfcFResp.contains(command)) - return NfcFResp[command]; - } - - return {}; + return eventNfcF(frame, prev); case nfc::TechType::NfcV: - if (frame->isPollFrame()) - { - int command = (*frame)[1]; - - if (NfcVCmd.contains(command)) - return NfcVCmd[command]; - - return QString("CMD %1").arg(command, 2, 16, QChar('0')); - } - - return {}; + return eventNfcV(frame, prev); } return {}; @@ -346,7 +244,7 @@ struct StreamModel::Impl data.append((*frame)[i]); } - return { data.toHex(' ') }; + return {data.toHex(' ')}; } // inline static QString frameData(const nfc::NfcFrame *frame) @@ -372,6 +270,156 @@ struct StreamModel::Impl // // return text.trimmed(); // } + + inline static QString eventNfcA(const nfc::NfcFrame *frame, const nfc::NfcFrame *prev) + { + QString result; + + // skip encrypted frames + if (frame->isEncrypted()) + return {}; + + if (frame->isPollFrame()) + { + int command = (*frame)[0]; + + // Protocol Parameter Selection + if (command == 0x50 && frame->limit() == 4) + return "HALT"; + + // Protocol Parameter Selection + if ((command & 0xF0) == 0xD0 && frame->limit() == 5) + return "PPS"; + + if (!(result = eventIsoDep(frame)).isEmpty()) + return result; + + if (NfcACmd.contains(command)) + return NfcACmd[command]; + } + else if (prev && prev->isPollFrame()) + { + int command = (*prev)[0]; + + if (command == 0x93 || command == 0x95 || command == 0x97) + { + if (frame->limit() == 3) + return "SAK"; + + if (frame->limit() == 5) + return "UID"; + } + + if (command == 0xE0 && (*frame)[0] == (frame->limit() - 2)) + return "ATS"; + + if (!(result = eventIsoDep(frame)).isEmpty()) + return result; + + if (NfcAResp.contains(command)) + return NfcAResp[command]; + } + + return {}; + } + + inline static QString eventNfcB(const nfc::NfcFrame *frame, const nfc::NfcFrame *prev) + { + QString result; + + if (frame->isPollFrame()) + { + int command = (*frame)[0]; + + if (!(result = eventIsoDep(frame)).isEmpty()) + return result; + + if (NfcBCmd.contains(command)) + return NfcBCmd[command]; + } + else if (frame->isListenFrame()) + { + int command = (*frame)[0]; + + if (!(result = eventIsoDep(frame)).isEmpty()) + return result; + + if (NfcBResp.contains(command)) + return NfcBResp[command]; + } + + return {}; + } + + inline static QString eventNfcF(const nfc::NfcFrame *frame, const nfc::NfcFrame *prev) + { + int command = (*frame)[1]; + + if (frame->isPollFrame()) + { + if (NfcFCmd.contains(command)) + return NfcFCmd[command]; + + return QString("CMD %1").arg(command, 2, 16, QChar('0')); + } + else if (frame->isListenFrame()) + { + if (NfcFResp.contains(command)) + return NfcFResp[command]; + } + + return {}; + } + + inline static QString eventNfcV(const nfc::NfcFrame *frame, const nfc::NfcFrame *prev) + { + if (frame->isPollFrame()) + { + int command = (*frame)[1]; + + if (NfcVCmd.contains(command)) + return NfcVCmd[command]; + + return QString("CMD %1").arg(command, 2, 16, QChar('0')); + } + + return {}; + } + + inline static QString eventIsoDep(const nfc::NfcFrame *frame) + { + int command = (*frame)[0]; + + // ISO-DEP protocol S(Deselect) + if ((command & 0xF7) == 0xC2 && frame->limit() == 3) + return "S(Deselect)"; + + // ISO-DEP protocol S(WTX) + if ((command & 0xF7) == 0xF2 && frame->limit() == 3) + return "S(WTX)"; + + // ISO-DEP protocol R(ACK) + if ((command & 0xF6) == 0xA2 && frame->limit() == 3) + return "R(ACK)"; + + // ISO-DEP protocol R(NACK) + if ((command & 0xF6) == 0xB2 && frame->limit() == 3) + return "R(NACK)"; + + // ISO-DEP protocol I-Block + if ((command & 0xE2) == 0x02 && frame->limit() >= 4) + return "I-Block"; + + // ISO-DEP protocol R-Block + if ((command & 0xE6) == 0xA2 && frame->limit() == 3) + return "R-Block"; + + // ISO-DEP protocol S-Block + if ((command & 0xC7) == 0xC2 && frame->limit() == 4) + return "S-Block"; + + return {}; + } }; StreamModel::StreamModel(QObject *parent) : QAbstractTableModel(parent), impl(new Impl) @@ -443,16 +491,28 @@ QVariant StreamModel::data(const QModelIndex &index, int role) const if (frame->isListenFrame()) return impl->responseDefaultFont; + + break; + } + + case Columns::Event: + { + if (frame->isListenFrame()) + return impl->responseDefaultFont; + + break; } } } else if (role == Qt::ForegroundRole) { - if (index.column() == Columns::Data) + switch (index.column()) { - if (frame->isListenFrame()) - return QColor(Qt::darkGray); + case Columns::Event: + case Columns::Data: + if (frame->isListenFrame()) + return QColor(Qt::darkGray); } } diff --git a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.cpp b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.cpp index 760b4c3a..58fc55fb 100644 --- a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.cpp +++ b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.cpp @@ -190,46 +190,22 @@ ProtocolFrame *ParserNfcIsoDep::parse(const nfc::NfcFrame &frame) { ProtocolFrame *info = nullptr; - if (frame.isPollFrame()) + if (frame.isPollFrame() || frame.isListenFrame()) { do { if (!frame.isEncrypted()) { // ISO-DEP protocol I-Block - if ((info = parseRequestIBlock(frame))) + if ((info = parseIBlock(frame))) break; // ISO-DEP protocol R-Block - if ((info = parseRequestRBlock(frame))) + if ((info = parseRBlock(frame))) break; // ISO-DEP protocol S-Block - if ((info = parseRequestSBlock(frame))) - break; - } - - // Unknown frame... - info = ParserNfc::parse(frame); - - } while (false); - } - else if (frame.isListenFrame()) - { - do - { - if (!frame.isEncrypted()) - { - // ISO-DEP protocol I-Block - if ((info = parseResponseIBlock(frame))) - break; - - // ISO-DEP protocol R-Block - if ((info = parseResponseRBlock(frame))) - break; - - // ISO-DEP protocol S-Block - if ((info = parseResponseSBlock(frame))) + if ((info = parseSBlock(frame))) break; } @@ -242,25 +218,18 @@ ProtocolFrame *ParserNfcIsoDep::parse(const nfc::NfcFrame &frame) return info; } -ProtocolFrame *ParserNfcIsoDep::parseRequestIBlock(const nfc::NfcFrame &frame) +ProtocolFrame *ParserNfcIsoDep::parseIBlock(const nfc::NfcFrame &frame) { - if ((frame[0] & 0xE2) != 0x02 || frame.limit() < 5) - return nullptr; - - lastCommand = frame[0]; - int pcb = frame[0], offset = 1; + if ((pcb & 0xE2) != 0x02 || frame.limit() < 4) + return nullptr; + ProtocolFrame *root = buildRootInfo("I-Block", frame, ProtocolFrame::ApplicationFrame); if (ProtocolFrame *pcbf = root->appendChild(buildChildInfo("PCB", frame, 0, 1))) { - if ((pcb & 0xC0) == 0x00) - pcbf->appendChild(buildChildInfo("[00....1.] I-Block")); - else if ((pcb & 0xC0) == 0x80) - pcbf->appendChild(buildChildInfo("[10....1.] R-Block")); - else if ((pcb & 0xC0) == 0xC0) - pcbf->appendChild(buildChildInfo("[11....1.] S-Block")); + pcbf->appendChild(buildChildInfo("[00....1.] I-Block")); if ((pcb & 0x10) == 0x00) pcbf->appendChild(buildChildInfo("[...0....] NO Chaining")); @@ -314,84 +283,13 @@ ProtocolFrame *ParserNfcIsoDep::parseRequestIBlock(const nfc::NfcFrame &frame) return root; } -ProtocolFrame *ParserNfcIsoDep::parseResponseIBlock(const nfc::NfcFrame &frame) +ProtocolFrame *ParserNfcIsoDep::parseRBlock(const nfc::NfcFrame &frame) { - if ((lastCommand & 0xE2) != 0x02) - return nullptr; - int pcb = frame[0], offset = 1; - int flags = 0; - - ProtocolFrame *root = buildRootInfo("", frame, ProtocolFrame::ApplicationFrame); - - if (ProtocolFrame *pcbf = root->appendChild(buildChildInfo("PCB", frame, 0, 1))) - { - pcbf->appendChild(buildChildInfo("[000...1.] I-Block")); - - if ((pcb & 0x10) == 0x00) - pcbf->appendChild(buildChildInfo("[...0....] NO Chaining")); - else - pcbf->appendChild(buildChildInfo("[...1....] Frame chaining")); - - if ((pcb & 0x08) == 0x00) - pcbf->appendChild(buildChildInfo("[....0...] NO CID following")); - else - pcbf->appendChild(buildChildInfo("[....1...] CID following")); - - if ((pcb & 0x04) == 0x00) - pcbf->appendChild(buildChildInfo("[.....0..] NO NAD following")); - else - pcbf->appendChild(buildChildInfo("[.....1..] NAD following")); - - if ((pcb & 0x01) == 0x00) - pcbf->appendChild(buildChildInfo("[.......0] Block number")); - else - pcbf->appendChild(buildChildInfo("[.......1] Block number")); - } - - if (pcb & 0x08) - { - root->appendChild(buildChildInfo("CID", frame[offset] & 0x0F, offset, 1)); - offset++; - } - - if (pcb & 0x04) - { - root->appendChild(buildChildInfo("NAD", frame[offset] & 0xFF, offset, 1)); - offset++; - } - - if (offset < frame.limit() - 2) - { - if (flags & IS_APDU) - { - if (offset < frame.limit() - 4) - { - root->appendChild(buildChildInfo("DATA", frame, offset, frame.limit() - offset - 4)); - } - - root->appendChild(buildChildInfo("SW", frame, -4, 2)); - } - else - { - root->appendChild(buildChildInfo("DATA", frame, offset, frame.limit() - offset - 2)); - } - } - - root->appendChild(buildChildInfo("CRC", frame, -2, 2)); - - return root; -} -ProtocolFrame *ParserNfcIsoDep::parseRequestRBlock(const nfc::NfcFrame &frame) -{ - if ((frame[0] & 0xE6) != 0xA2 || frame.limit() != 3) + if ((pcb & 0xE6) != 0xA2 || frame.limit() != 3) return nullptr; - lastCommand = frame[0]; - - int pcb = frame[0], offset = 1; - ProtocolFrame *root; if (pcb & 0x10) @@ -406,7 +304,7 @@ ProtocolFrame *ParserNfcIsoDep::parseRequestRBlock(const nfc::NfcFrame &frame) if ((pcb & 0x10) == 0x00) pcbf->appendChild(buildChildInfo("[...0....] ACK")); else - pcbf->appendChild(buildChildInfo("[...1....] NAK")); + pcbf->appendChild(buildChildInfo("[...1....] NACK")); if ((pcb & 0x08) == 0x00) pcbf->appendChild(buildChildInfo("[....0...] NO CID following")); @@ -433,23 +331,13 @@ ProtocolFrame *ParserNfcIsoDep::parseRequestRBlock(const nfc::NfcFrame &frame) return root; } -ProtocolFrame *ParserNfcIsoDep::parseResponseRBlock(const nfc::NfcFrame &frame) +ProtocolFrame *ParserNfcIsoDep::parseSBlock(const nfc::NfcFrame &frame) { - if ((lastCommand & 0xE6) != 0xA2) - return nullptr; - - return buildRootInfo("", frame, ProtocolFrame::ApplicationFrame); -} + int pcb = frame[0], offset = 1; -ProtocolFrame *ParserNfcIsoDep::parseRequestSBlock(const nfc::NfcFrame &frame) -{ - if ((frame[0] & 0xC7) != 0xC2 || frame.limit() != 4) + if ((pcb & 0xC7) != 0xC2 || frame.limit() < 3 || frame.limit() > 4) return nullptr; - lastCommand = frame[0]; - - int pcb = frame[0], offset = 1; - ProtocolFrame *root = buildRootInfo("S-Block", frame, ProtocolFrame::ApplicationFrame); if (ProtocolFrame *pcbf = root->appendChild(buildChildInfo("PCB", frame, 0, 1))) @@ -480,12 +368,3 @@ ProtocolFrame *ParserNfcIsoDep::parseRequestSBlock(const nfc::NfcFrame &frame) return root; } - -ProtocolFrame *ParserNfcIsoDep::parseResponseSBlock(const nfc::NfcFrame &frame) -{ - if ((lastCommand & 0xC7) != 0xC2) - return nullptr; - - return buildRootInfo("", frame, ProtocolFrame::ApplicationFrame); -} - diff --git a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.h b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.h index 71d18beb..7df201f3 100644 --- a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.h +++ b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfc.h @@ -73,17 +73,11 @@ struct ParserNfcIsoDep : ParserNfc ProtocolFrame *parse(const nfc::NfcFrame &frame) override; - ProtocolFrame *parseRequestIBlock(const nfc::NfcFrame &frame); + ProtocolFrame *parseIBlock(const nfc::NfcFrame &frame); - ProtocolFrame *parseResponseIBlock(const nfc::NfcFrame &frame); + ProtocolFrame *parseRBlock(const nfc::NfcFrame &frame); - ProtocolFrame *parseRequestRBlock(const nfc::NfcFrame &frame); - - ProtocolFrame *parseResponseRBlock(const nfc::NfcFrame &frame); - - ProtocolFrame *parseRequestSBlock(const nfc::NfcFrame &frame); - - ProtocolFrame *parseResponseSBlock(const nfc::NfcFrame &frame); + ProtocolFrame *parseSBlock(const nfc::NfcFrame &frame); }; #endif //NFC_LAB_PARSERNFC_H diff --git a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfcA.cpp b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfcA.cpp index 1440b5f1..ce7c1c78 100644 --- a/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfcA.cpp +++ b/src/nfc-app/app-qt/src/main/cpp/parser/ParserNfcA.cpp @@ -74,7 +74,7 @@ ProtocolFrame *ParserNfcA::parse(const nfc::NfcFrame &frame) break; } - // Unknown frame... + // Unknown frame... try isoDep info = ParserNfcIsoDep::parse(frame); } while (false); @@ -120,7 +120,7 @@ ProtocolFrame *ParserNfcA::parse(const nfc::NfcFrame &frame) break; } - // Unknown frame... + // Unknown frame... try isoDep info = ParserNfcIsoDep::parse(frame); } while (false); From b95a53c76f1b822078e800377f2670330819c708 Mon Sep 17 00:00:00 2001 From: Jose Vicente Campos Date: Sun, 12 Jun 2022 19:16:03 +0200 Subject: [PATCH 2/3] fixed IsoDep protocol parser --- src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp b/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp index a6fc9ea1..3046c4bd 100644 --- a/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp +++ b/src/nfc-app/app-qt/src/main/cpp/model/StreamModel.cpp @@ -391,11 +391,11 @@ struct StreamModel::Impl int command = (*frame)[0]; // ISO-DEP protocol S(Deselect) - if ((command & 0xF7) == 0xC2 && frame->limit() == 3) + if ((command & 0xF7) == 0xC2 && frame->limit() >= 3 && frame->limit() <= 4) return "S(Deselect)"; // ISO-DEP protocol S(WTX) - if ((command & 0xF7) == 0xF2 && frame->limit() == 3) + if ((command & 0xF7) == 0xF2 && frame->limit() >= 3 && frame->limit() <= 4) return "S(WTX)"; // ISO-DEP protocol R(ACK) @@ -415,7 +415,7 @@ struct StreamModel::Impl return "R-Block"; // ISO-DEP protocol S-Block - if ((command & 0xC7) == 0xC2 && frame->limit() == 4) + if ((command & 0xC7) == 0xC2 && frame->limit() >= 3 && frame->limit() <= 4) return "S-Block"; return {}; From 11831e24b76f8cd8d4ade0fe7b53c6dc586583c9 Mon Sep 17 00:00:00 2001 From: Jose Vicente Campos Date: Sun, 12 Jun 2022 19:20:32 +0200 Subject: [PATCH 3/3] release 2.8.1 --- CMakeLists.txt | 2 +- src/nfc-app/app-qt/src/main/cpp/QtConfig.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62fdfb7d..d427c169 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.17) -project(nfc-lab VERSION 2.8.0) +project(nfc-lab VERSION 2.8.1) set(CMAKE_C_FLAGS_DEBUG "-g -msse -msse3 -mno-avx -fno-math-errno -falign-functions=32 -falign-loops=32" CACHE INTERNAL "" FORCE) set(CMAKE_CXX_FLAGS_DEBUG "-g -msse -msse3 -mno-avx -fno-math-errno -falign-functions=32 -falign-loops=32" CACHE INTERNAL "" FORCE) diff --git a/src/nfc-app/app-qt/src/main/cpp/QtConfig.h b/src/nfc-app/app-qt/src/main/cpp/QtConfig.h index 0cf6352b..97e5bc09 100644 --- a/src/nfc-app/app-qt/src/main/cpp/QtConfig.h +++ b/src/nfc-app/app-qt/src/main/cpp/QtConfig.h @@ -3,6 +3,6 @@ */ #define NFC_LAB_VERSION_MAJOR 2 #define NFC_LAB_VERSION_MINOR 8 -#define NFC_LAB_VERSION_PATCH 0 -#define NFC_LAB_VERSION_STRING "2.8.0" -#define NFC_LAB_VENDOR_STRING "NFC laboratory 2.8.0 - josevcm@gmail.com" +#define NFC_LAB_VERSION_PATCH 1 +#define NFC_LAB_VERSION_STRING "2.8.1" +#define NFC_LAB_VENDOR_STRING "NFC laboratory 2.8.1 - josevcm@gmail.com"