From 1be76882044528e4a9d5e53234c94713521e92bf Mon Sep 17 00:00:00 2001
From: Maxie Dion Schmidt <maxieds@gmail.com>
Date: Mon, 21 Mar 2022 21:05:16 -0400
Subject: [PATCH] Adding more complete support for PM3 ISO auth (stashing
 incremental changes as reference point -- II)

---
 .../DESFire/DESFireISO14443Support.c          |  2 +-
 .../DESFire/DESFireISO14443Support.h          |  2 +-
 .../Chameleon-Mini/Application/ISO14443-3A.c  |  4 ++--
 .../Chameleon-Mini/Application/ISO14443-3A.h  |  6 ------
 .../Application/MifareDESFire.c               | 20 ++++++++++---------
 5 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c
index eb84692b..58345e88 100644
--- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c
+++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c
@@ -359,7 +359,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
             return ISO14443A_ATQA_FRAME_SIZE_BYTES * BITS_PER_BYTE;
 
         case ISO14443_3A_STATE_READY1:
-            if (Cmd == ISO14443A_CMD_SELECT_CL1 || Cmd == ISO14443A_CMD_REQA || ISO14443ACmdIsWUPA(Cmd)) {
+            if (Cmd == ISO14443A_CMD_SELECT_CL1) {
                 /* Load UID CL1 and perform anticollision. */
                 ConfigurationUidType Uid;
                 ApplicationGetUid(Uid);
diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.h
index bf56f7db..9c68f63f 100644
--- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.h
+++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.h
@@ -112,7 +112,7 @@ INLINE ISO14443AStoreLastDataFrameAndReturn(const uint8_t *Buffer, uint16_t Buff
 
 /* Setup some fuzzy response handling for problematic readers like the ACR122U */
 
-#define MAX_STATE_RETRY_COUNT               (0x04)   /* For all intensive purposes, as many as necessary */
+#define MAX_STATE_RETRY_COUNT               (0x0a)   /* For all intensive purposes, as many as necessary */
 extern uint8_t StateRetryCount;
 bool CheckStateRetryCount(bool resetByDefault);
 bool CheckStateRetryCount2(bool resetByDefault, bool performLogging);
diff --git a/Firmware/Chameleon-Mini/Application/ISO14443-3A.c b/Firmware/Chameleon-Mini/Application/ISO14443-3A.c
index cc7192b4..06812994 100644
--- a/Firmware/Chameleon-Mini/Application/ISO14443-3A.c
+++ b/Firmware/Chameleon-Mini/Application/ISO14443-3A.c
@@ -19,6 +19,8 @@ bool ISO14443ASelectDesfire(void *Buffer, uint16_t *BitCount, uint8_t *UidCL, ui
     uint8_t NVB = DataPtr[1];
 
     switch (NVB) {
+        case 0x00:
+        case ISO14443A_CMD_HLTA:        
         case ISO14443A_NVB_AC_START:
             /* Start of anticollision procedure.
              * Send whole UID CLn + BCC          */
@@ -162,8 +164,6 @@ bool ISO14443ASelect(void *Buffer, uint16_t *BitCount, uint8_t *UidCL, uint8_t S
     uint8_t NVB = DataPtr[1];
 
     switch (NVB) {
-        case 0x00:
-        case ISO14443A_CMD_HLTA:
         case ISO14443A_NVB_AC_START:
             /* Start of anticollision procedure.
             * Send whole UID CLn + BCC */
diff --git a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h
index d83f0b66..cefe7dbd 100644
--- a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h
+++ b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h
@@ -25,12 +25,6 @@
 #define ISO14443A_NVB_AC_START      0x20
 #define ISO14443A_NVB_AC_END        0x70
 
-#define IsSelectCmd(Buffer)         ((Buffer[0] == ISO14443A_CMD_SELECT_CL1) || \
-				     (Buffer[0] == ISO14443A_CMD_SELECT_CL2) || \
-				     (Buffer[0] == ISO14443A_CMD_SELECT_CL3))
-#define IsCmdSelectRound1(Buffer)   (IsSelectCmd(Buffer) && (Buffer[1] == ISO14443A_NVB_AC_START))
-#define IsCmdSelectRound2(Buffer)   (IsSelectCmd(Buffer) && (Buffer[1] == ISO14443A_NVB_AC_END))
-
 #define ISO14443A_CL_UID_OFFSET     0
 #define ISO14443A_CL_UID_SIZE       4
 #define ISO14443A_CL_BCC_OFFSET     4
diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c
index 2b57edad..d7e1e8cc 100644
--- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c
+++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c
@@ -111,15 +111,13 @@ void MifareDesfireAppReset(void) {
     /* This is called repeatedly, so limit the amount of work done */
     ISO144433AReset();
     ISO144434Reset();
-    StateRetryCount = MAX_STATE_RETRY_COUNT;
     MifareDesfireReset();
 }
 
 void MifareDesfireAppTick(void) {
-    if (!CheckStateRetryCount2(false, false)) {
+    if (CheckStateRetryCount2(false, true)) {
         MifareDesfireAppReset();
     }
-    /* Empty */
 }
 
 void MifareDesfireAppTask(void) {
@@ -176,12 +174,13 @@ uint16_t MifareDesfireProcessCommand(uint8_t *Buffer, uint16_t ByteCount) {
 uint16_t MifareDesfireProcess(uint8_t *Buffer, uint16_t BitCount) {
     size_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
     DesfireCmdCLA = Buffer[0];
-    //LogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, Buffer, ByteCount);
+    LogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, Buffer, ByteCount);
     if (BitCount == 0) {
         LogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, Buffer, ByteCount);
         return ISO14443A_APP_NO_RESPONSE;
     } else if ((ByteCount >= 8 && DesfireCLA(Buffer[0]) && Buffer[2] == 0x00 &&
-                Buffer[3] == 0x00 && (Buffer[4] == ByteCount - 6 || Buffer[4] == ByteCount - 8)) || Iso7816CLA(DesfireCmdCLA)) {
+                Buffer[3] == 0x00 && (Buffer[4] == ByteCount - 6 || Buffer[4] == ByteCount - 8)) || 
+                Iso7816CLA(DesfireCmdCLA)) {
         /* Wrapped native command structure or ISO7816: */
         if (Iso7816CLA(DesfireCmdCLA)) {
             uint16_t iso7816ParamsStatus = SetIso7816WrappedParametersType(Buffer, ByteCount);
@@ -204,9 +203,9 @@ uint16_t MifareDesfireProcess(uint8_t *Buffer, uint16_t BitCount) {
             Buffer[ByteCount - 1] = 0x91;
             ++ByteCount;
         } else {
-            /* Re-wrap into ISO 7816-4 */
+            /* Re-wrap into ISO 7816-4 -- Done below by prepending the prologue back to the buffer */
         }
-        //LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, Buffer, ByteCount);
+        LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, Buffer, ByteCount);
         return ByteCount * BITS_PER_BYTE;
     } else {
         /* ISO/IEC 14443-4 PDUs: No extra work */
@@ -233,16 +232,19 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
         memcpy(&ISO7816PrologueBytes[0], Buffer, 2);
         if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) {
             memmove(&Buffer[0], &Buffer[2], ByteCount - 2);
+            ByteCount = ByteCount - 2;
         } else if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3RAW) {
-            /* Looks something like: 0a 00 1a 00 CRC1 CRC2 (for PM3 raw ISO auth) */
+            /* Something like the following (for PM3 raw ISO auth): 
+             * 0a 00 1a 00 CRC1 CRC2 -- first two are prologue -- last two are checksum */
             Buffer[0] = DesfireCmdCLA;
             Buffer[1] = Buffer[2];
             memmove(&Buffer[5], &Buffer[3], ByteCount - 3);
             Buffer[2] = 0x00;
             Buffer[3] = 0x00;
             Buffer[4] = ByteCount - 5;
+            ByteCount = ByteCount + 3;
         }
-        uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount);
+        uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, ByteCount);
         uint16_t UnwrappedBitCount = (IncomingByteCount - 2) * BITS_PER_BYTE;
         uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount);
         uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;