Chameleon-Mini
DESFireISO14443Support.h
1 /*
2 The DESFire stack portion of this firmware source
3 is free software written by Maxie Dion Schmidt (@maxieds):
4 You can redistribute it and/or modify
5 it under the terms of this license.
6 
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 
11 The complete source distribution of
12 this firmware is available at the following link:
13 https://github.com/maxieds/ChameleonMiniFirmwareDESFireStack.
14 
15 Based in part on the original DESFire code created by
16 @dev-zzo (GitHub handle) [Dmitry Janushkevich] available at
17 https://github.com/dev-zzo/ChameleonMini/tree/desfire.
18 
19 This notice must be retained at the top of all source files where indicated.
20 */
21 
22 /*
23  * DESFireISO14443Support.h
24  * Maxie D. Schmidt (github.com/maxieds)
25  */
26 
27 #ifndef __DESFIRE_ISO14443_SUPPORT_H__
28 #define __DESFIRE_ISO14443_SUPPORT_H__
29 
30 #include "DESFireFirmwareSettings.h"
31 
32 #include "../ISO14443-3A.h"
33 #include "../../Codec/ISO14443-2A.h"
34 
35 /* General structure of a ISO 14443-4 block:
36  * PCB (protocol control byte)
37  * CID (card identifier byte; presence controlled by PCB)
38  * NAD (node address byte; presence controlled by PCB)
39  * Payload (arbitrary bytes)
40  * CRC-16
41  */
42 
43 #define ISO14443A_CMD_RATS 0xE0
44 #define ISO14443A_RATS_FRAME_SIZE (6 * BITS_PER_BYTE) //(4 * 8) /* Bit */
45 #define ISO14443A_CMD_RNAK 0xB2
46 #define ISO14443A_CRC_FRAME_SIZE (ISO14443A_CRCA_SIZE * BITS_PER_BYTE)
47 
48 #define ISO14443_PCB_BLOCK_TYPE_MASK 0xC0
49 #define ISO14443_PCB_I_BLOCK 0x00
50 #define ISO14443_PCB_R_BLOCK 0x80
51 #define ISO14443_PCB_S_BLOCK 0xC0
52 
53 #define ISO14443_PCB_I_BLOCK_STATIC 0x02
54 #define ISO14443_PCB_R_BLOCK_STATIC 0xA2
55 #define ISO14443_PCB_S_BLOCK_STATIC 0xC2
56 
57 #define ISO14443_PCB_BLOCK_NUMBER_MASK 0x01
58 #define ISO14443_PCB_HAS_NAD_MASK 0x04
59 #define ISO14443_PCB_HAS_CID_MASK 0x08
60 #define ISO14443_PCB_I_BLOCK_CHAINING_MASK 0x10
61 #define ISO14443_PCB_R_BLOCK_ACKNAK_MASK 0x10
62 #define ISO14443_PCB_R_BLOCK_ACK 0x00
63 #define ISO14443_PCB_R_BLOCK_NAK 0x10
64 
65 #define ISO14443_R_BLOCK_SIZE 1 /* Bytes */
66 
67 #define ISO14443_PCB_S_DESELECT (ISO14443_PCB_S_BLOCK_STATIC)
68 #define ISO14443_PCB_S_DESELECT_V2 0xCA
69 #define ISO14443_PCB_S_WTX (ISO14443_PCB_S_BLOCK_STATIC | 0x30)
70 #define ISO14443A_CMD_PPS 0xD0
71 
72 #define IS_ISO14443A_4_COMPLIANT(buf) (buf[0] & 0x20)
73 #define MAKE_ISO14443A_4_COMPLIANT(buf) (buf[0] |= 0x20)
74 
75 /*
76  * ISO/IEC 14443-4 implementation
77  * To support EV2 cards emulation, proper support for handling 14443-4
78  * blocks will be implemented.
79  * Currently NOT supported:
80  * + Block chaining
81  * + Frame waiting time extension
82  */
83 
84 typedef enum DESFIRE_FIRMWARE_ENUM_PACKING {
85  ISO14443_4_STATE_EXPECT_RATS,
86  ISO14443_4_STATE_ACTIVE,
87  ISO14443_4_STATE_LAST,
88 } Iso144434StateType;
89 
90 extern Iso144434StateType Iso144434State;
91 extern uint8_t Iso144434BlockNumber;
92 extern uint8_t Iso144434CardID;
93 extern uint8_t LastReaderSentCmd;
94 
95 /* Setup some fuzzy response handling for problematic readers like the ACR122U */
96 #define MAX_STATE_RETRY_COUNT (4)
97 extern uint8_t StateRetryCount;
98 bool CheckStateRetryCount(bool resetByDefault);
99 bool CheckStateRetryCount2(bool resetByDefault, bool performLogging);
100 
101 #define IGNORE_ACK_BYTE (0x92)
102 
103 /* Support functions */
104 void ISO144434SwitchState(Iso144434StateType NewState);
105 void ISO144434SwitchState2(Iso144434StateType NewState, bool performLogging);
106 
107 void ISO144434Reset(void);
108 static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint16_t BitCount);
109 
110 /*
111  * ISO/IEC 14443-3A implementation
112  */
113 #define ISO14443A_CRCA_INIT ((uint16_t) 0x6363)
114 
115 #define GetAndSetBufferCRCA(Buffer, ByteCount) ({ \
116  uint16_t fullReturnBits = 0; \
117  ISO14443AAppendCRCA(Buffer, ByteCount); \
118  fullReturnBits = ByteCount * BITS_PER_BYTE + ISO14443A_CRC_FRAME_SIZE; \
119  fullReturnBits; \
120  })
121 /* TODO: Should we return CRC bytes when giving a NO_RESPONSE ??? ... Apparently "No". */
122 #define GetAndSetNoResponseCRCA(Buffer) ({ \
123  uint16_t fullReturnBits = 0; \
124  ISO14443AAppendCRCA(Buffer, 0); \
125  fullReturnBits = ISO14443A_CRC_FRAME_SIZE; \
126  fullReturnBits; \
127  })
128 
129 uint16_t ISO14443AUpdateCRCA(const uint8_t *Buffer, uint16_t ByteCount, uint16_t InitCRCA);
130 
131 typedef enum DESFIRE_FIRMWARE_ENUM_PACKING {
132  /* The card is powered up but not selected */
133  ISO14443_3A_STATE_IDLE = ISO14443_4_STATE_LAST,
134  /* Entered on REQA or WUPA; anticollision is being performed */
135  ISO14443_3A_STATE_READY1,
136  ISO14443_3A_STATE_READY2,
137  /* Entered when the card has been selected */
138  ISO14443_3A_STATE_ACTIVE,
139  /* Something went wrong or we've received a halt command */
140  ISO14443_3A_STATE_HALT,
141 } Iso144433AStateType;
142 
143 extern Iso144433AStateType Iso144433AState;
144 extern Iso144433AStateType Iso144433AIdleState;
145 
146 /* Support functions */
147 void ISO144433ASwitchState(Iso144433AStateType NewState);
148 void ISO144433AReset(void);
149 void ISO144433AHalt(void);
150 bool ISO144433AIsHalt(const uint8_t *Buffer, uint16_t BitCount);
151 uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount);
152 
153 #endif