M5Unit-NFC 0.1.2 git rev:63c4caa
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 <m5_utility/conversion.hpp>
17#include <array>
18#include <algorithm>
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 default_rx_capacity(const m5::nfc::isodep::IsoDEP& dep)
48{
49 const uint16_t cfg_rx = dep.config().max_frame_size_rx();
50 const uint16_t base = cfg_rx ? cfg_rx : 256;
51 return std::max<uint16_t>(256, base);
52}
53
54inline void pack_le24(uint8_t out[3], const uint32_t value)
55{
56 out[0] = static_cast<uint8_t>(value & 0xFF);
57 out[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
58 out[2] = static_cast<uint8_t>((value >> 16) & 0xFF);
59}
60
61inline void pack_be24(uint8_t out[3], const uint32_t value)
62{
63 out[0] = static_cast<uint8_t>((value >> 16) & 0xFF);
64 out[1] = static_cast<uint8_t>((value >> 8) & 0xFF);
65 out[2] = static_cast<uint8_t>(value & 0xFF);
66}
67
68inline uint32_t unpack_le24(const uint8_t in[3])
69{
70 return static_cast<uint32_t>(in[0]) | (static_cast<uint32_t>(in[1]) << 8) | (static_cast<uint32_t>(in[2]) << 16);
71}
72
74} // namespace detail
75
81 uint8_t file_type{};
82 uint8_t comm_mode{};
83 uint16_t access_rights{};
84 uint32_t file_size{};
85};
86
92 uint8_t aid[3]{}; // BE
93 uint8_t _pad{};
94 inline constexpr uint32_t aid24() const noexcept
95 {
96 // Big-endian
97 return ((uint32_t)aid[0] << 16) | ((uint32_t)aid[1] << 8) | aid[2];
98 }
99 inline constexpr const uint8_t* data() const noexcept
100 {
101 return aid;
102 }
103 inline explicit operator uint32_t() const noexcept
104 {
105 return aid24();
106 }
107};
108inline bool operator==(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
109{
110 return a.aid[0] == b.aid[0] && a.aid[1] == b.aid[1] && a.aid[2] == b.aid[2];
111}
112inline bool operator!=(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
113{
114 return !(a == b);
115}
116inline bool operator<(const desfire_aid_t& a, const desfire_aid_t& b) noexcept
117{
118 return a.aid24() < b.aid24();
119}
120
125enum class AuthMode : uint8_t {
126 Auto,
127 DES,
128 AES,
129};
130
151
157 uint8_t old_file_no{};
158 uint8_t new_file_no{};
159 uint16_t new_file_id{};
160};
161
167 uint8_t ti[4]{};
168 uint16_t cmd_ctr{};
169 uint8_t ses_enc_key[16]{};
170 uint8_t ses_mac_key[16]{};
171};
180std::vector<uint8_t> make_native_wrap_command(const uint8_t ins, const uint8_t* data = nullptr,
181 const uint16_t data_len = 0);
182
189inline uint8_t status_code(const uint8_t* rx, const uint16_t rx_len)
190{
191 return (rx && rx_len >= 2 && rx[rx_len - 2] == 0x91) ? rx[rx_len - 1] : 0xFF;
192}
193
200inline bool is_successful(const uint8_t* rx, const uint16_t rx_len)
201{
202 return status_code(rx, rx_len) == 0x00;
203}
204
211inline bool is_more(const uint8_t* rx, const uint16_t rx_len)
212{
213 return status_code(rx, rx_len) == 0xAF;
214}
215
222inline bool is_duplicate(const uint8_t* rx, const uint16_t rx_len)
223{
224 return status_code(rx, rx_len) == 0xDE;
225}
226
232public:
237 explicit DESFireFileSystem(m5::nfc::NFCLayerA& layer);
243 {
244 }
245
256 m5::stl::expected<void, uint8_t> createApplication(const uint8_t aid[3], const uint8_t key_settings1,
257 const uint8_t key_settings2, const uint16_t iso_fid = 0,
258 const uint8_t* df_name = nullptr, const uint8_t df_name_len = 0);
264 inline bool selectApplication(const desfire_aid_t& aid)
265 {
266 return selectApplication(aid.data());
267 }
273 bool selectApplication(const uint8_t aid[3]);
279 bool selectApplication(const uint32_t aid24 = 0u);
285 bool deleteApplication(const uint8_t aid[3]);
286
292 bool getApplicationIDs(std::vector<desfire_aid_t>& out);
299 bool getFreeMemory(uint32_t& out);
306 bool getKeySettings(uint8_t& key_settings, uint8_t& key_count);
312 bool getFileIDs(std::vector<uint8_t>& out);
318 bool getISOFileIDs(std::vector<uint8_t>& out);
325 bool getFileSettings(FileSettings& out, const uint8_t file_no);
333 bool getFileSettingsEV2(FileSettings& out, const uint8_t file_no, Ev2Context& ctx);
341 bool getFileSettingsEV2Full(FileSettings& out, const uint8_t file_no, Ev2Context& ctx);
342
350 bool changeFileSettings(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights);
359 bool changeFileSettingsEV2(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights,
360 Ev2Context& ctx);
369 bool changeFileSettingsEV2Full(const uint8_t file_no, const uint8_t file_option, const uint16_t access_rights,
370 Ev2Context& ctx);
371
378 bool formatPICC(const uint8_t* picc_master_key, const AuthMode mode = AuthMode::Auto);
379
389 bool createStdDataFile(const uint8_t file_no, const uint16_t iso_fid, const uint8_t comm_mode,
390 const uint16_t access_rights, const uint32_t file_size);
391
398 bool setConfigurationFileRenaming(const FileRename& first, const FileRename* second = nullptr);
406 bool setConfigurationFileRenamingEV2Full(const FileRename& first, const FileRename* second, Ev2Context& ctx);
407
415 bool deleteTransactionMACFileEV2Full(const uint8_t file_no, Ev2Context& ctx);
416
427 bool createTransactionMACFileEV2Full(const uint8_t file_no, const uint8_t comm_mode, const uint16_t access_rights,
428 const uint8_t tmac_key[16], const uint8_t tmac_key_ver, Ev2Context& ctx);
437 bool setConfigurationAppNameEV2Full(const uint8_t* df_name, uint8_t df_name_len, uint16_t iso_fid, Ev2Context& ctx);
438
447 bool readData(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset, const uint32_t length);
456 bool readDataLight(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset, const uint32_t length);
466 bool readDataLightEV2Full(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset,
467 const uint32_t length, Ev2Context& ctx);
477 bool readDataLightEV2(std::vector<uint8_t>& out, const uint8_t file_no, const uint32_t offset,
478 const uint32_t length, Ev2Context& ctx);
487 bool writeData(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len);
496 bool writeDataLight(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len);
506 bool writeDataLightEV2(const uint8_t file_no, const uint32_t offset, const uint8_t* data, const uint32_t data_len,
507 Ev2Context& ctx);
517 bool writeDataLightEV2Full(const uint8_t file_no, const uint32_t offset, const uint8_t* data,
518 const uint32_t data_len, Ev2Context& ctx);
519
526 bool authenticateDES(const uint8_t key_no, const uint8_t key[16]);
533 bool authenticateISO(const uint8_t key_no, const uint8_t key[16]);
540 bool authenticateAES(const uint8_t key_no, const uint8_t key[16]);
548 bool authenticateEV2First(const uint8_t key_no, const uint8_t key[16], Ev2Context& ctx);
549
550protected:
551 bool transceive(uint8_t* rx, uint16_t& rx_len, const uint8_t* tx, const uint16_t tx_len);
552};
553
554} // namespace desfire
555} // namespace mifare
556} // namespace a
557} // namespace nfc
558} // namespace m5
559#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:231
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:1279
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:1292
bool authenticateDES(const uint8_t key_no, const uint8_t key[16])
Authenticate with DES key (legacy)
Definition desfire_file_system.cpp:1329
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:1081
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:1305
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:990
bool getFileIDs(std::vector< uint8_t > &out)
Get list of file IDs in the currently selected application.
Definition desfire_file_system.cpp:1136
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:745
DESFireFileSystem(m5::nfc::isodep::IsoDEP &isoDEP)
Constructor with IsoDEP.
Definition desfire_file_system.hpp:242
bool getApplicationIDs(std::vector< desfire_aid_t > &out)
Get list of application IDs.
Definition desfire_file_system.cpp:902
bool getFileSettings(FileSettings &out, const uint8_t file_no)
Get file settings (plain)
Definition desfire_file_system.cpp:1180
bool authenticateAES(const uint8_t key_no, const uint8_t key[16])
Authenticate with AES key.
Definition desfire_file_system.cpp:1339
bool getFileSettingsEV2Full(FileSettings &out, const uint8_t file_no, Ev2Context &ctx)
Get file settings (EV2 Full)
Definition desfire_file_system.cpp:1249
bool getFreeMemory(uint32_t &out)
Get free memory of PICC.
Definition desfire_file_system.cpp:934
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:1112
bool getKeySettings(uint8_t &key_settings, uint8_t &key_count)
Get key settings of the currently selected application.
Definition desfire_file_system.cpp:968
bool selectApplication(const desfire_aid_t &aid)
Select application by desfire_aid_t.
Definition desfire_file_system.hpp:264
bool setConfigurationFileRenaming(const FileRename &first, const FileRename *second=nullptr)
Set file renaming configuration (DESFire Light; requires AppMasterKey + CommMode.Full)
Definition desfire_file_system.cpp:1025
bool getISOFileIDs(std::vector< uint8_t > &out)
Get list of ISO file IDs in the currently selected application.
Definition desfire_file_system.cpp:1160
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:836
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:802
bool deleteTransactionMACFileEV2Full(const uint8_t file_no, Ev2Context &ctx)
Delete TransactionMAC file (required for ISOReadBinary to work)
Definition desfire_file_system.cpp:1103
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:1443
bool setConfigurationFileRenamingEV2Full(const FileRename &first, const FileRename *second, Ev2Context &ctx)
Set file renaming configuration (EV2 Full)
Definition desfire_file_system.cpp:1056
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:1219
bool authenticateISO(const uint8_t key_no, const uint8_t key[16])
Authenticate with ISO key.
Definition desfire_file_system.cpp:1334
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:211
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:222
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:125
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:200
uint8_t status_code(const uint8_t *rx, const uint16_t rx_len)
DESFire status code (0x91xx)
Definition desfire_file_system.hpp:189
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:166
uint8_t ses_mac_key[16]
Session MAC key.
Definition desfire_file_system.hpp:170
uint16_t cmd_ctr
Command Counter.
Definition desfire_file_system.hpp:168
uint8_t ses_enc_key[16]
Session ENC key.
Definition desfire_file_system.hpp:169
uint8_t ti[4]
Transaction Identifier.
Definition desfire_file_system.hpp:167
File renaming parameters for DESFire Light SetConfiguration.
Definition desfire_file_system.hpp:156
uint16_t new_file_id
New ISO File ID (LSB first in command)
Definition desfire_file_system.hpp:159
uint8_t new_file_no
New file number.
Definition desfire_file_system.hpp:158
uint8_t old_file_no
Current file number.
Definition desfire_file_system.hpp:157
DESFire file settings (minimal fields for StdDataFile)
Definition desfire_file_system.hpp:80
Options for formatting DESFire as Type4 NDEF.
Definition desfire_file_system.hpp:135
uint8_t key_settings1
AN11004: Create/Delete requires auth, Get* requires auth.
Definition desfire_file_system.hpp:145
uint8_t aid[3]
NDEF Tag Application AID.
Definition desfire_file_system.hpp:137
const uint8_t * app_master_key
DES/3DES master key (App), or nullptr to skip auth.
Definition desfire_file_system.hpp:148
uint8_t comm_mode
Plain communication.
Definition desfire_file_system.hpp:143
uint16_t ndef_file_size
NDEF file size (bytes)
Definition desfire_file_system.hpp:142
const uint8_t * picc_master_key
DES/3DES master key (PICC), or nullptr to skip auth.
Definition desfire_file_system.hpp:147
AuthMode auth_mode
Authentication mode.
Definition desfire_file_system.hpp:149
uint16_t cc_file_size
CC file size (bytes)
Definition desfire_file_system.hpp:141
uint16_t access_rights
DESFire access rights.
Definition desfire_file_system.hpp:144
uint8_t key_settings2
ISO FID support(bit5) + NumKeys=1 + DES/3DES.
Definition desfire_file_system.hpp:146
m5::nfc::ndef::type4::CapabilityContainer cc
CC contents.
Definition desfire_file_system.hpp:136
uint8_t ndef_file_no
NDEF file number (DESFire)
Definition desfire_file_system.hpp:140
uint8_t cc_file_no
CC file number (DESFire)
Definition desfire_file_system.hpp:139
24bit Application ID
Definition desfire_file_system.hpp:91
uint16_t max_frame_size_rx() const
Maximum receive frame size.
Definition isoDEP.hpp:182
Capability container for Type4.
Definition ndef.hpp:460