M5Unit-NFC 0.1.0 git rev:93745b5
Loading...
Searching...
No Matches
desfire_file_system.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_UNIFIED_NFC_NFC_ISODEP_DESFIRE_FILE_SYSTEM_HPP
11#define M5_UNIT_UNIFIED_NFC_NFC_ISODEP_DESFIRE_FILE_SYSTEM_HPP
12#include "file_system.hpp"
13#include "nfc/a/mifare.hpp"
14#include "nfc/ndef/ndef.hpp"
15#include <m5_utility/stl/expected.hpp>
16#include <array>
17#include <algorithm>
18#include <limits>
19
20namespace m5 {
21namespace nfc {
22class NFCLayerA;
23namespace a {
24namespace mifare {
29namespace desfire {
30
31constexpr uint8_t DESFIRE_APDU_CLA{0x90};
32constexpr uint8_t DESFIRE_LIGHT_INS_READ_DATA{0xAD};
33constexpr uint8_t DESFIRE_LIGHT_INS_WRITE_DATA{0x8D};
34
37using file_no_t = uint8_t;
41
43
44namespace detail {
46
47inline uint16_t clamp_u16_size(const size_t size)
48{
49 constexpr size_t max_u16 = std::numeric_limits<uint16_t>::max();
50 return static_cast<uint16_t>(size > max_u16 ? max_u16 : size);
51}
52
53inline uint16_t default_rx_capacity(const m5::nfc::isodep::IsoDEP& dep)
54{
55 const uint16_t cfg_rx = dep.config().max_frame_size_rx();
56 const uint16_t base = cfg_rx ? cfg_rx : 256;
57 return std::max<uint16_t>(256, base);
58}
59
60inline void pack_le24(uint8_t out[3], const uint32_t value)
61{
62 out[0] = static_cast<uint8_t>(value & 0xFF);
63 out[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
64 out[2] = static_cast<uint8_t>((value >> 16) & 0xFF);
65}
66
67inline void pack_be24(uint8_t out[3], const uint32_t value)
68{
69 out[0] = static_cast<uint8_t>((value >> 16) & 0xFF);
70 out[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
71 out[2] = static_cast<uint8_t>(value & 0xFF);
72}
73
74inline uint32_t unpack_le24(const uint8_t in[3])
75{
76 return static_cast<uint32_t>(in[0]) | (static_cast<uint32_t>(in[1]) << 8) | (static_cast<uint32_t>(in[2]) << 16);
77}
78
80} // namespace detail
81
87 uint8_t file_type{};
88 uint8_t comm_mode{};
89 uint16_t access_rights{};
90 uint32_t file_size{};
91};
92
98 uint8_t aid[3]{}; // BE
99 uint8_t _pad{};
100 inline constexpr uint32_t aid24() const noexcept
101 {
102 // Big-endian
103 return ((uint32_t)aid[0] << 16) | ((uint32_t)aid[1] << 8) | aid[2];
104 }
105 inline constexpr const uint8_t* data() const noexcept
106 {
107 return aid;
108 }
109 inline explicit operator uint32_t() const noexcept
110 {
111 return aid24();
112 }
113};
114inline bool operator==(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
115{
116 return a.aid[0] == b.aid[0] && a.aid[1] == b.aid[1] && a.aid[2] == b.aid[2];
117}
118inline bool operator!=(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
119{
120 return !(a == b);
121}
122inline bool operator<(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
123{
124 return a.aid24() < b.aid24();
125}
126
131enum class AuthMode : uint8_t {
132 Auto,
133 DES,
134 AES,
135};
136
157
163 uint8_t old_file_no{};
164 uint8_t new_file_no{};
165 uint16_t new_file_id{};
166};
167
173 uint8_t ti[4]{};
174 uint16_t cmd_ctr{};
175 uint8_t ses_enc_key[16]{};
176 uint8_t ses_mac_key[16]{};
177};
186std::vector<uint8_t> make_native_wrap_command(const uint8_t ins, const uint8_t* data = nullptr,
187 const uint16_t data_len = 0);
188
195inline uint8_t status_code(const uint8_t* rx, const uint16_t rx_len)
196{
197 return (rx && rx_len >= 2 && rx[rx_len - 2] == 0x91) ? rx[rx_len - 1] : 0xFF;
198}
199
206inline bool is_successful(const uint8_t* rx, const uint16_t rx_len)
207{
208 return status_code(rx, rx_len) == 0x00;
209}
210
217inline bool is_more(const uint8_t* rx, const uint16_t rx_len)
218{
219 return status_code(rx, rx_len) == 0xAF;
220}
221
228inline bool is_duplicate(const uint8_t* rx, const uint16_t rx_len)
229{
230 return status_code(rx, rx_len) == 0xDE;
231}
232
238public:
243 explicit DESFireFileSystem(m5::nfc::NFCLayerA& layer);
249 {
250 }
251
262 m5::stl::expected<void, uint8_t> createApplication(const uint8_t aid[3], const uint8_t key_settings1,
263 const uint8_t key_settings2, const uint16_t iso_fid = 0,
264 const uint8_t* df_name = nullptr, const uint8_t df_name_len = 0);
270 inline bool selectApplication(const desfire_aid_t& aid)
271 {
272 return selectApplication(aid.data());
273 }
279 bool selectApplication(const uint8_t aid[3]);
285 bool selectApplication(const uint32_t aid24 = 0u);
291 bool deleteApplication(const uint8_t aid[3]);
292
298 bool getApplicationIDs(std::vector<desfire_aid_t>& out);
305 bool getFreeMemory(uint32_t& out);
312 bool getKeySettings(uint8_t& key_settings, uint8_t& key_count);
318 bool getFileIDs(std::vector<uint8_t>& out);
324 bool getISOFileIDs(std::vector<uint8_t>& out);
331 bool getFileSettings(FileSettings& out, const uint8_t file_no);
339 bool getFileSettingsEV2(FileSettings& out, const uint8_t file_no, Ev2Context& ctx);
347 bool getFileSettingsEV2Full(FileSettings& out, const uint8_t file_no, Ev2Context& ctx);
348
356 bool changeFileSettings(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights);
365 bool changeFileSettingsEV2(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights,
366 Ev2Context& ctx);
375 bool changeFileSettingsEV2Full(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights,
376 Ev2Context& ctx);
377
384 bool formatPICC(const uint8_t* picc_master_key, const AuthMode mode = AuthMode::Auto);
385
395 bool createStdDataFile(const uint8_t file_no, const uint16_t iso_fid, const uint8_t comm_mode,
396 const uint16_t access_rights, const uint32_t file_size);
397
404 bool setConfigurationFileRenaming(const FileRename& first, const FileRename* second = nullptr);
412 bool setConfigurationFileRenamingEV2Full(const FileRename& first, const FileRename* second, Ev2Context& ctx);
413
421 bool deleteTransactionMACFileEV2Full(const uint8_t file_no, Ev2Context& ctx);
422
433 bool createTransactionMACFileEV2Full(const uint8_t file_no, const uint8_t comm_mode, const uint16_t access_rights,
434 const uint8_t tmac_key[16], const uint8_t tmac_key_ver, Ev2Context& ctx);
443 bool setConfigurationAppNameEV2Full(const uint8_t* df_name, uint8_t df_name_len, uint16_t iso_fid, Ev2Context& ctx);
444
453 bool readData(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset, const uint32_t length);
462 bool readDataLight(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset, const uint32_t length);
472 bool readDataLightEV2Full(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset,
473 const uint32_t length, Ev2Context& ctx);
483 bool readDataLightEV2(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset,
484 const uint32_t length, Ev2Context& ctx);
493 bool writeData(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len);
502 bool writeDataLight(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len);
512 bool writeDataLightEV2(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len,
513 Ev2Context& ctx);
523 bool writeDataLightEV2Full(const uint8_t file_no, const uint32_t offset, const uint8_t* data,
524 const uint32_t data_len, Ev2Context& ctx);
525
532 bool authenticateDES(const uint8_t key_no, const uint8_t key[16]);
539 bool authenticateISO(const uint8_t key_no, const uint8_t key[16]);
546 bool authenticateAES(const uint8_t key_no, const uint8_t key[16]);
554 bool authenticateEV2First(const uint8_t key_no, const uint8_t key[16], Ev2Context& ctx);
555
556protected:
557 bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len);
558};
559
560} // namespace desfire
561} // namespace mifare
562} // namespace a
563} // namespace nfc
564} // namespace m5
565#endif
ISO/IEC 7816-4 file system.
Definition file_system.hpp:81
Common interface layer for each chip of the NFC-A reader.
Definition nfc_layer_a.hpp:43
File system for MIFARE DESFire.
Definition desfire_file_system.hpp:237
bool changeFileSettingsEV2Full(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights, Ev2Context &ctx)
Change file settings (EV2 Full)
Definition desfire_file_system.cpp:1267
bool changeFileSettingsEV2(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights, Ev2Context &ctx)
Change file settings (EV2 MAC)
Definition desfire_file_system.cpp:1280
bool authenticateDES(const uint8_t key_no, const uint8_t key[16])
Authenticate with DES key (legacy)
Definition desfire_file_system.cpp:1317
bool setConfigurationAppNameEV2Full(const uint8_t *df_name, uint8_t df_name_len, uint16_t iso_fid, Ev2Context &ctx)
Change application name/ISO file ID (EV2 Full)
Definition desfire_file_system.cpp:1069
DESFireFileSystem(m5::nfc::NFCLayerA &layer)
Constructor with NFCLayerA.
Definition desfire_file_system.cpp:477
bool createStdDataFile(const uint8_t file_no, const uint16_t iso_fid, const uint8_t comm_mode, const uint16_t access_rights, const uint32_t file_size)
Create a Standard Data File.
Definition desfire_file_system.cpp:536
bool changeFileSettings(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights)
Change file settings (plain)
Definition desfire_file_system.cpp:1293
bool formatPICC(const uint8_t *picc_master_key, const AuthMode mode=AuthMode::Auto)
Format the PICC (erases all applications and files)
Definition desfire_file_system.cpp:978
bool getFileIDs(std::vector< uint8_t > &out)
Get list of file IDs in the currently selected application.
Definition desfire_file_system.cpp:1124
bool readDataLight(std::vector< uint8_t > &out, const uint8_t file_no, const uint32_t offset, const uint32_t length)
Read data from DESFire Light file.
Definition desfire_file_system.cpp:618
m5::stl::expected< void, uint8_t > createApplication(const uint8_t aid[3], const uint8_t key_settings1, const uint8_t key_settings2, const uint16_t iso_fid=0, const uint8_t *df_name=nullptr, const uint8_t df_name_len=0)
Create a new application.
Definition desfire_file_system.cpp:482
bool deleteApplication(const uint8_t aid[3])
Delete application by 3-byte AID.
Definition desfire_file_system.cpp:521
bool writeDataLight(const uint8_t file_no, const uint32_t offset, const uint8_t *data, const uint32_t data_len)
Write data to DESFire Light file.
Definition desfire_file_system.cpp:739
DESFireFileSystem(m5::nfc::isodep::IsoDEP &isoDEP)
Constructor with IsoDEP.
Definition desfire_file_system.hpp:248
bool getApplicationIDs(std::vector< desfire_aid_t > &out)
Get list of application IDs.
Definition desfire_file_system.cpp:890
bool getFileSettings(FileSettings &out, const uint8_t file_no)
Get file settings (plain)
Definition desfire_file_system.cpp:1168
bool authenticateAES(const uint8_t key_no, const uint8_t key[16])
Authenticate with AES key.
Definition desfire_file_system.cpp:1327
bool getFileSettingsEV2Full(FileSettings &out, const uint8_t file_no, Ev2Context &ctx)
Get file settings (EV2 Full)
Definition desfire_file_system.cpp:1237
bool getFreeMemory(uint32_t &out)
Get free memory of PICC.
Definition desfire_file_system.cpp:922
bool createTransactionMACFileEV2Full(const uint8_t file_no, const uint8_t comm_mode, const uint16_t access_rights, const uint8_t tmac_key[16], const uint8_t tmac_key_ver, Ev2Context &ctx)
Create TransactionMAC file.
Definition desfire_file_system.cpp:1100
bool getKeySettings(uint8_t &key_settings, uint8_t &key_count)
Get key settings of the currently selected application.
Definition desfire_file_system.cpp:956
bool selectApplication(const desfire_aid_t &aid)
Select application by desfire_aid_t.
Definition desfire_file_system.hpp:270
bool setConfigurationFileRenaming(const FileRename &first, const FileRename *second=nullptr)
Set file renaming configuration (DESFire Light; requires AppMasterKey + CommMode.Full)
Definition desfire_file_system.cpp:1013
bool getISOFileIDs(std::vector< uint8_t > &out)
Get list of ISO file IDs in the currently selected application.
Definition desfire_file_system.cpp:1148
bool writeDataLightEV2Full(const uint8_t file_no, const uint32_t offset, const uint8_t *data, const uint32_t data_len, Ev2Context &ctx)
Write data to DESFire Light file (EV2 Full)
Definition desfire_file_system.cpp:824
bool readData(std::vector< uint8_t > &out, const uint8_t file_no, const uint32_t offset, const uint32_t length)
Read data from DESFire file.
Definition desfire_file_system.cpp:566
bool writeDataLightEV2(const uint8_t file_no, const uint32_t offset, const uint8_t *data, const uint32_t data_len, Ev2Context &ctx)
Write data to DESFire Light file (EV2 MAC)
Definition desfire_file_system.cpp:790
bool deleteTransactionMACFileEV2Full(const uint8_t file_no, Ev2Context &ctx)
Delete TransactionMAC file (required for ISOReadBinary to work)
Definition desfire_file_system.cpp:1091
bool readDataLightEV2(std::vector< uint8_t > &out, const uint8_t file_no, const uint32_t offset, const uint32_t length, Ev2Context &ctx)
Read data from DESFire Light file (EV2 MAC)
Definition desfire_file_system.cpp:665
bool writeData(const uint8_t file_no, const uint32_t offset, const uint8_t *data, const uint32_t data_len)
Write data to DESFire file.
Definition desfire_file_system.cpp:684
bool authenticateEV2First(const uint8_t key_no, const uint8_t key[16], Ev2Context &ctx)
Authenticate (AuthenticateEV2First, AES) and prepare EV2 context.
Definition desfire_file_system.cpp:1431
bool setConfigurationFileRenamingEV2Full(const FileRename &first, const FileRename *second, Ev2Context &ctx)
Set file renaming configuration (EV2 Full)
Definition desfire_file_system.cpp:1044
bool readDataLightEV2Full(std::vector< uint8_t > &out, const uint8_t file_no, const uint32_t offset, const uint32_t length, Ev2Context &ctx)
Read data from DESFire Light file (EV2 Full)
Definition desfire_file_system.cpp:646
bool getFileSettingsEV2(FileSettings &out, const uint8_t file_no, Ev2Context &ctx)
Get file settings (EV2 MAC)
Definition desfire_file_system.cpp:1207
bool authenticateISO(const uint8_t key_no, const uint8_t key[16])
Authenticate with ISO key.
Definition desfire_file_system.cpp:1322
ISO Data Exchange Protocol.
Definition isoDEP.hpp:240
config_t config() const
Get configuration.
Definition isoDEP.hpp:262
bool is_more(const uint8_t *rx, const uint16_t rx_len)
Is the received data still waiting for a response?
Definition desfire_file_system.hpp:217
constexpr file_no_t MAXIMUM_FILE_NO
Maximum file number.
Definition desfire_file_system.hpp:39
uint8_t file_no_t
Alias for file number.
Definition desfire_file_system.hpp:37
bool is_duplicate(const uint8_t *rx, const uint16_t rx_len)
Is duplicate error? (e.g. app/file already exists)
Definition desfire_file_system.hpp:228
constexpr uint8_t MAXIMUM_FILES
Files max.
Definition desfire_file_system.hpp:42
constexpr file_no_t MINIMUM_FILE_NO
Minimum file number.
Definition desfire_file_system.hpp:38
AuthMode
Authentication mode.
Definition desfire_file_system.hpp:131
bool is_successful(const uint8_t *rx, const uint16_t rx_len)
Is the status of the received data successful?
Definition desfire_file_system.hpp:206
uint8_t status_code(const uint8_t *rx, const uint16_t rx_len)
DESFire status code (0x91xx)
Definition desfire_file_system.hpp:195
File system base using isoDEP.
MIFARE definitions.
constexpr uint8_t DESFIRE_CC_FILE_NO
AN11004 default CC file number.
Definition mifare.hpp:195
constexpr uint8_t DESFIRE_NDEF_FILE_NO
AN11004 default NDEF file number.
Definition mifare.hpp:196
constexpr uint8_t DESFIRE_NDEF_AID[]
DESFire NDEF AID (3 bytes)
Definition mifare.hpp:197
NFC-A definitions.
NFC-B definitions.
Top level namespace of M5Stack.
For MIFARE.
NFC related definitions.
NDEF related.
bool operator==(const PICC &a, const PICC &b)
Equal?
Definition nfca.hpp:669
bool operator!=(const PICC &a, const PICC &b)
Not equal?
Definition nfca.hpp:675
Session context for EV2 secure messaging.
Definition desfire_file_system.hpp:172
uint8_t ses_mac_key[16]
Session MAC key.
Definition desfire_file_system.hpp:176
uint16_t cmd_ctr
Command Counter.
Definition desfire_file_system.hpp:174
uint8_t ses_enc_key[16]
Session ENC key.
Definition desfire_file_system.hpp:175
uint8_t ti[4]
Transaction Identifier.
Definition desfire_file_system.hpp:173
File renaming parameters for DESFire Light SetConfiguration.
Definition desfire_file_system.hpp:162
uint16_t new_file_id
New ISO File ID (LSB first in command)
Definition desfire_file_system.hpp:165
uint8_t new_file_no
New file number.
Definition desfire_file_system.hpp:164
uint8_t old_file_no
Current file number.
Definition desfire_file_system.hpp:163
DESFire file settings (minimal fields for StdDataFile)
Definition desfire_file_system.hpp:86
Options for formatting DESFire as Type4 NDEF.
Definition desfire_file_system.hpp:141
uint8_t key_settings1
AN11004: Create/Delete requires auth, Get* requires auth.
Definition desfire_file_system.hpp:151
uint8_t aid[3]
NDEF Tag Application AID.
Definition desfire_file_system.hpp:143
const uint8_t * app_master_key
DES/3DES master key (App), or nullptr to skip auth.
Definition desfire_file_system.hpp:154
uint8_t comm_mode
Plain communication.
Definition desfire_file_system.hpp:149
uint16_t ndef_file_size
NDEF file size (bytes)
Definition desfire_file_system.hpp:148
const uint8_t * picc_master_key
DES/3DES master key (PICC), or nullptr to skip auth.
Definition desfire_file_system.hpp:153
AuthMode auth_mode
Authentication mode.
Definition desfire_file_system.hpp:155
uint16_t cc_file_size
CC file size (bytes)
Definition desfire_file_system.hpp:147
uint16_t access_rights
DESFire access rights.
Definition desfire_file_system.hpp:150
uint8_t key_settings2
ISO FID support(bit5) + NumKeys=1 + DES/3DES.
Definition desfire_file_system.hpp:152
m5::nfc::ndef::type4::CapabilityContainer cc
CC contents.
Definition desfire_file_system.hpp:142
uint8_t ndef_file_no
NDEF file number (DESFire)
Definition desfire_file_system.hpp:146
uint8_t cc_file_no
CC file number (DESFire)
Definition desfire_file_system.hpp:145
24bit Application ID
Definition desfire_file_system.hpp:97
uint16_t max_frame_size_rx() const
Maximum receive frame size.
Definition isoDEP.hpp:182
Capability container for Type4.
Definition ndef.hpp:459