M5Unit-NFC 0.0.3 git rev:59f5362
Loading...
Searching...
No Matches
apdu.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_APDU_APDU_HPP
11#define M5_UNIT_UNIFIED_NFC_NFC_APDU_APDU_HPP
12#include <cstdint>
13#include <string>
14#include <vector>
15
16namespace m5 {
17namespace nfc {
22namespace apdu {
23
27constexpr uint16_t RESPONSE_OK{0x9000};
29constexpr uint16_t SUCCESSFULLY_1{0x6100};
31constexpr uint16_t SUCCESSFULLY_2{0x9F00};
32
33constexpr uint8_t RESPONSE_BYTES_STILL_AVAILABLE{0x61};
34constexpr uint8_t WRONG_LENGTH_LE{0x6C};
36
38inline bool is_response_OK(const uint16_t sw12)
39{
40 return sw12 == RESPONSE_OK || ((sw12 & 0xFF00) == SUCCESSFULLY_1) || ((sw12 & 0xFF00) == SUCCESSFULLY_2);
41}
42
44inline bool is_response_OK(const uint8_t sw[2])
45{
46 return is_response_OK((uint16_t)((sw[0] << 8) | sw[1]));
47}
49inline bool is_response_OK(const uint8_t sw1, const uint8_t sw2)
50{
51 return is_response_OK((uint16_t)((sw1 << 8) | sw2));
52}
53
58enum class INS : uint8_t {
59 // ISO/IEC 7816-4
60 SELECT_FILE = 0xA4,
61 CREATE_FILE = 0xE0,
62
63 READ_BINARY = 0xB0,
64 WRITE_BINARY = 0xD0,
65 UPDATE_BINARY = 0xD6,
66 ERASE_BINARY = 0x0E,
67
68 READ_RECORD = 0xB2,
69 WRITE_RECORD = 0xD2,
70 APPEND_RECORD = 0xE2,
71 UPDATE_RECORRD = 0xDC,
72
73 GET_RESPONSE = 0xC0,
74 GET_DATA = 0xCA,
75 PUT_DATA = 0xDA,
76
77 VERIFY = 0x20,
78
79 INTERNAL_AUTHENTICATE = 0x88,
80 EXTERNAL_AUTHENTICATE = 0x82,
81
82 GET_CHALLEMGE = 0x84,
83
84 // Not ISO/IEC 7816-4
85 LOCK_DF = 0x50,
86 UNLOCK_DF = 0x52,
87 UNLOCK_KEY = 0x54,
88 CHANGE_KEY = 0x32,
89 ERASE_ALL_RECORDS = 0x06,
90 GET_VERSION = 0x60,
91
92 // DESFire
93 DF_CREATE_APPLICATION = 0xCA,
94 DF_DELETE_APPLICATION = 0xDA,
95 DF_SELECT_APPLICATION = 0x5A,
96 DF_GET_APPLICATION_IDS = 0x6A,
97 DF_CREATE_STD_DATA_FILE = 0xCD,
98 DF_GET_FREE_MEMORY = 0x6E,
99 DF_GET_FILE_IDS = 0x6F,
100 DF_GET_ISO_FILE_IDS = 0x61,
101 DF_GET_KEY_SETTINGS = 0x45,
102 DF_SET_CONFIGURATION = 0x5C,
103 DF_CHANGE_FILE_SETTINGS = 0x5F,
104 DF_AUTHENTICATE = 0x0A,
105 DF_AUTHENTICATE_ISO = 0x1A,
106 DF_AUTHENTICATE_AES = 0xAA,
107 DF_AUTHENTICATE_EV2 = 0x71,
108 DF_FORMAT_PICC = 0xFC,
109 DF_READ_DATA = 0xBD,
110 DF_WRITE_DATA = 0x3D,
111 DF_GET_FILE_SETTINGS = 0xF5,
112 DF_DELETE_TRANSACTION_MAC_FILE = 0xDF,
113 DF_CREATE_TRANSACTION_MAC_FILE = 0xCE,
114};
116
122enum class SelectBy : uint8_t {
123 FileId = 0x00,
124 ChildDf = 0x01,
125 EfUnderCurrentDf = 0x02,
126 ParentDf = 0x03,
127 DfName = 0x04,
128 PathFromMf = 0x08,
129 PathFromCurrentDf = 0x09,
130};
131
137enum class SelectOccurrence : uint8_t {
138 FirstOrOnly = 0x00,
139 Last = 0x01,
140 Next = 0x02,
141 Previous = 0x03,
142};
143
148enum class SelectResponse : uint8_t {
149 FCI = 0x00,
150 FCP = 0x04,
151 FMD = 0x08,
152 None = 0x0C,
153};
154
155constexpr uint16_t master_file_id{0x3F00};
156
157inline bool need_select_file_le(const uint8_t param2)
158{
159 return (param2 & 0x0C) != 0x0C;
160}
161
166struct TLV {
167 uint32_t tag{};
168 uint32_t len{};
169 const uint8_t* v{};
170 uint8_t tag_len{};
171
172 inline bool is_constructed() const
173 {
174 return (tag & 0x20) != 0;
175 }
176 inline bool is_primitive() const
177 {
178 return !is_constructed();
179 }
180};
181
183std::vector<TLV> parse_tlv(const uint8_t* ptr, const uint32_t len);
185void dump_tlv(const std::vector<TLV>& tlvs, const uint8_t depth = 0);
186
198std::vector<uint8_t> make_apdu_command(const uint8_t cla, const uint8_t ins, const uint8_t param1 = 0x00,
199 const uint8_t param2 = 0x00, const uint8_t* data = nullptr,
200 const uint16_t data_len = 0, const uint16_t rx_len = 0);
201
203inline std::vector<uint8_t> make_apdu_case1(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2)
204{
205 return make_apdu_command(cla, ins, p1, p2, nullptr, 0, 0);
206}
207
209inline std::vector<uint8_t> make_apdu_case2(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2,
210 const uint16_t le)
211{
212 return make_apdu_command(cla, ins, p1, p2, nullptr, 0, le);
213}
214
216inline std::vector<uint8_t> make_apdu_case3(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2,
217 const uint8_t* data, const uint16_t data_len)
218{
219 return make_apdu_command(cla, ins, p1, p2, data, data_len, 0);
220}
221
223inline std::vector<uint8_t> make_apdu_case4(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2,
224 const uint8_t* data, const uint16_t data_len, const uint16_t le)
225{
226 return make_apdu_command(cla, ins, p1, p2, data, data_len, le);
227}
228
229} // namespace apdu
230} // namespace nfc
231} // namespace m5
232#endif
std::vector< uint8_t > make_apdu_command(const uint8_t cla, const uint8_t ins, const uint8_t param1, const uint8_t param2, const uint8_t *data, const uint16_t data_len, const uint16_t rx_len)
Make APDU command.
Definition apdu.cpp:22
SelectBy
Select control for SELECT_FILE.
Definition apdu.hpp:122
@ EfUnderCurrentDf
Select EF under current DF (FID in data)
@ FileId
Select MF/DF/EF by file ID.
@ DfName
Select by DF name (AID)
@ ChildDf
Select child DF (FID in data)
@ PathFromMf
Select by path from MF.
@ PathFromCurrentDf
Select by path from current DF.
@ ParentDf
Select parent DF.
constexpr uint16_t RESPONSE_OK
Command successfully executed (OK)
Definition apdu.hpp:27
constexpr uint16_t SUCCESSFULLY_2
Command successfully executed; xx bytes of data are available and can be requested using GET RESPON.
Definition apdu.hpp:31
std::vector< uint8_t > make_apdu_case1(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2)
Make APDU case1 command [CLA | INS | P1 | P2].
Definition apdu.hpp:203
SelectResponse
Response for SELECT_FILE.
Definition apdu.hpp:148
constexpr uint8_t WRONG_LENGTH_LE
Wrong length Le.
Definition apdu.hpp:34
std::vector< uint8_t > make_apdu_case2(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint16_t le)
Make APDU case2 command [CLA | INS | P1 | P2 | Le].
Definition apdu.hpp:209
INS
APDU instruction code.
Definition apdu.hpp:58
constexpr uint8_t RESPONSE_BYTES_STILL_AVAILABLE
Response bytes still available.
Definition apdu.hpp:33
constexpr uint16_t SUCCESSFULLY_1
Command successfully executed; xx bytes of data are available and can be requested using GET RESPON.
Definition apdu.hpp:29
SelectOccurrence
Select occurrence for SELECT_FILE.
Definition apdu.hpp:137
@ Next
Select the next match.
@ FirstOrOnly
Select the first (or only) match.
@ Last
Select the last match.
@ Previous
Select the previous match.
constexpr uint16_t master_file_id
Master file ID.
Definition apdu.hpp:155
bool is_response_OK(const uint16_t sw12)
Is response successfully?
Definition apdu.hpp:38
std::vector< uint8_t > make_apdu_case4(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint8_t *data, const uint16_t data_len, const uint16_t le)
Make APDU case4 command [CLA | INS | P1 | P2 | Lc | C-Data | Le].
Definition apdu.hpp:223
std::vector< uint8_t > make_apdu_case3(const uint8_t cla, const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint8_t *data, const uint16_t data_len)
Make APDU case3 command [CLA | INS | P1 | P2 | Lc | C-Data].
Definition apdu.hpp:216
For APDU.
Top level namespace of M5stack.
NFC related definitions.
NFC-V definitions.
File Control Parameters.
Definition file_system.hpp:26
TLV element.
Definition apdu.hpp:166
uint32_t len
L (length)
Definition apdu.hpp:168
uint8_t tag_len
Tag length.
Definition apdu.hpp:170
uint32_t tag
T (Tag)
Definition apdu.hpp:167