This repository was archived by the owner on Aug 28, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnfc_framework.hpp
More file actions
executable file
·203 lines (181 loc) · 6.64 KB
/
nfc_framework.hpp
File metadata and controls
executable file
·203 lines (181 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
* This file is part of the Capibara zero project(https://capibarazero.github.io/).
* Copyright (c) 2024 Andrea Canale.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFCFramework_H
#define NFCFramework_H
#include <Arduino.h>
#include <Wire.h>
#include "Adafruit_PN532.h"
#include <SPI.h>
#include <vector>
// Some Mifare definitions
#define MIFARE_CLASSIC_SIZE 1024
#define MIFARE_CLASSIC_BLOCKS 64
#define MIFARE_ULTRALIGHT_SIZE 512
#define MIFARE_ULTRALIGHT_BLOCKS 16
#define MIFARE_IS_ULTRALIGHT(uid_length) (uid_length > 4)
#define BLOCK_SIZE 16 // Default block size
// Some NFCTAG21xx definitions
#define NTAG_PAGE_SIZE 4
#define NTAG203_PAGES 42
#define NTAG213_PAGES 45
#define NTAG215_PAGES 135
#define NTAG216_PAGES 231
#define NTAG203_RESERVED_PAGES 3
#define NTAG21X_RESERVED_PAGES 6
// FeliCa definitions
#define DEFAULT_SYSTEM_CODE 0xFFFF
#define DEFAULT_REQUEST_CODE 0x01
// Manufacturer codes for FeliCa cards as per Sony documentation
enum FelicaManufacturer {
ISO18092 = 0x01FE,
TYPE3 = 0x02FE,
PLUG_LITE = 0x03FE,
STANDARD = 0x04FE, // First digit is random
UNREGISTERED = 0x05FE
};
// System codes for FeliCa cards as per Sony documentation
enum FelicaSystemCodes {
INVALID = 0xFFFF,
NDEF = 0x12FC,
NFC_F = 0x4000,
LITE_S = 0x88B4,
SECURE_ID = 0x957A,
COMMON_AREA = 0xFE00,
PLUG = 0xFEE1
};
typedef struct DumpResult{
uint8_t unreadable = 0;
uint8_t unauthenticated = 0;
} DumpResult;
typedef enum KeyType {
KEY_A,
KEY_B
} KeyType;
typedef struct Key {
KeyType type;
uint8_t data[6];
} Key;
typedef struct TagType {
const char *name;
uint16_t atqa;
uint8_t sak;
uint8_t uid_length;
uint8_t blocks;
} TagType;
#define MIFARE_CLASSIC_1K (TagType){"Mifare Classic 1K", 0x04, 0x08, 4, 64}
// #define MIFARE_CLASSIC_4K (TagType){0x04, 0x03, 16, 264 }
#define MIFARE_MINI (TagType){"Mifare Mini",0x04, 0x09, 4, 20}
// Debug macros
#ifdef ESP32S3_DEVKITC_BOARD
#define SERIAL_DEVICE Serial0
#else
#define SERIAL_DEVICE Serial
#endif
#define LOG_ERROR(reason) SERIAL_DEVICE.printf("\e[31m%s\e[0m", reason)
#define LOG_SUCCESS(reason) SERIAL_DEVICE.printf("\e[32m%s\e[0m", reason)
#define LOG_INFO(reason) SERIAL_DEVICE.printf("%s", reason)
class NFCFramework
{
private:
Adafruit_PN532 *nfc;
void print_block(int currentblock, uint8_t *block);
void print_error(int block_number, const char *reason);
uint8_t *prepare_tag_store(uint8_t *tag_data, size_t tag_size);
// Create JIS system code(0xAA00 to 0xAAFE) dynamically to save some memory
void fill_JIS_system_code(uint8_t *out);
public:
// NFCFramework(int sck, int miso, int mosi, int ss);
NFCFramework(uint8_t sck, uint8_t miso, uint8_t mosi, uint8_t ss){
nfc = new Adafruit_PN532(sck, miso, mosi, ss);
LOG_INFO("Init NFC Framework");
nfc->begin();
nfc->SAMConfig();
}
NFCFramework(uint8_t irq, uint8_t rst){
nfc = new Adafruit_PN532(irq, rst);
LOG_INFO("Init NFC Framework");
nfc->begin();
nfc->SAMConfig();
}
~NFCFramework();
bool ready();
void power_down() {
nfc->reset();
nfc->begin();
nfc->SAMConfig();
}
uint32_t get_version() {
return nfc->getFirmwareVersion();
}
void printHex(byte *data, uint32_t length) {
for (uint8_t i = 0; i < length; i++) {
if (data[i] < 0x10) {
LOG_INFO(" 0");
} else {
LOG_INFO(' ');
}
SERIAL_DEVICE.print(data[i], HEX);
}
}
static TagType lookup_tag(uint16_t atqa, uint8_t sak, uint8_t uid_len) {
if (atqa == 0x04 && sak == 0x08 && uid_len == MIFARE_CLASSIC_1K.uid_length) {
return MIFARE_CLASSIC_1K;
} else if (atqa == 0x04 && sak == 0x09 && uid_len == MIFARE_MINI.uid_length) {
return MIFARE_MINI;
} else {
return (TagType){"Unknown", 0, 0, 0, 20};
}
}
// Generic ISO14443A functions
int get_tag_uid(uint8_t *uid, uint8_t length);
int get_tag_uid(uint8_t *uid, uint8_t *length);
int get_tag_uid(uint8_t *uid, uint8_t *length, uint16_t *atqa, uint8_t *sak);
// Mifare functions
bool auth_tag(uint8_t *key, uint8_t block_number, KeyType key_type);
bool write_tag(size_t block_number, uint8_t *data, uint8_t key_type, uint8_t *key);
bool read_block(uint8_t block, uint8_t *key, KeyType key_type, uint8_t *out);
// uint8_t *dump_tag(uint8_t key[], size_t *uid_length);
uint8_t* dump_tag(uint8_t key[], size_t *uid_length, DumpResult *result);
uint8_t* dump_tag(Key *key, uint8_t blocks, DumpResult *result);
// NFCTAG21xx functions
uint8_t *dump_ntag2xx_tag(size_t pages);
bool write_ntag2xx_page(size_t page, uint8_t *data);
// FeliCa functions
int felica_polling(uint8_t *idm, uint8_t *pmm, uint16_t *response_code);
int felica_polling(uint8_t system_code, uint8_t *idm, uint8_t *pmm, uint16_t *response_code);
int felica_polling(uint8_t system_code, uint8_t request_code ,uint8_t *idm, uint8_t *pmm, uint16_t *response_code);
int felica_read_without_encryption(uint8_t service_codes_list_length, uint16_t *service_codes, uint8_t block_number, uint16_t *block_list, uint8_t data[][16]);
int felica_write_without_encryption(uint8_t service_codes_list_length, uint16_t *service_codes, uint8_t block_number, uint16_t *block_list, uint8_t data[][16]);
void felica_release() { nfc->felica_Release(); };
bool emulate_tag(uint8_t *uid) {
uint8_t empty[10];
memset(empty, 0, 10);
return nfc->AsTarget(uid, empty, empty, empty);
};
bool emulate_tag(uint8_t *idm, uint8_t *pmm, uint8_t *sys_code) {
uint8_t empty[10];
memset(empty, 0, 10);
return nfc->AsTarget(empty, idm, pmm, sys_code);
};
// EMV methods created with the help of https://werner.rothschopf.net/201703_arduino_esp8266_nfc.htm
std::vector<uint8_t> emv_ask_for_aid();
std::vector<uint8_t> emv_ask_for_app_name();
std::vector<uint8_t> emv_ask_for_pdol(std::vector<uint8_t> *aid);
std::vector<uint8_t> emv_ask_for_afl();
std::vector<uint8_t> emv_read_afl(uint8_t p2);
};
#endif