Skip to content

Commit 6cdcc9a

Browse files
committed
feat(nfc): add DESFire protocol and emulation
1 parent 24b3e38 commit 6cdcc9a

4 files changed

Lines changed: 930 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#ifndef MF_DESFIRE_H
2+
#define MF_DESFIRE_H
3+
4+
#include <stdint.h>
5+
#include <stddef.h>
6+
#include <stdbool.h>
7+
8+
#include "highboy_nfc_error.h"
9+
#include "highboy_nfc_types.h"
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
#define MF_DESFIRE_CLA 0x90
16+
#define MF_DESFIRE_CMD_ADDITIONAL 0xAF
17+
#define MF_DESFIRE_SW_OK 0x9100
18+
#define MF_DESFIRE_SW_MORE 0x91AF
19+
20+
#define MF_DESFIRE_CMD_GET_VERSION 0x60
21+
#define MF_DESFIRE_CMD_SELECT_APP 0x5A
22+
#define MF_DESFIRE_CMD_GET_APP_IDS 0x6A
23+
#define MF_DESFIRE_CMD_GET_KEY_SET 0x45
24+
#define MF_DESFIRE_CMD_AUTH_3DES 0x0A
25+
#define MF_DESFIRE_CMD_AUTH_AES 0xAA
26+
#define MF_DESFIRE_CMD_AUTH_EV2_FIRST 0x71
27+
#define MF_DESFIRE_CMD_AUTH_EV2_NONFIRST 0x77
28+
#define MF_DESFIRE_CMD_GET_FILE_IDS 0x6F
29+
#define MF_DESFIRE_CMD_READ_DATA 0xBD
30+
#define MF_DESFIRE_CMD_WRITE_DATA 0x3D
31+
#define MF_DESFIRE_CMD_COMMIT_TRANSACTION 0xC7
32+
#define MF_DESFIRE_CMD_ABORT_TRANSACTION 0xA7
33+
34+
typedef enum {
35+
MF_DESFIRE_KEY_DES = 0,
36+
MF_DESFIRE_KEY_2K3DES,
37+
MF_DESFIRE_KEY_3K3DES,
38+
MF_DESFIRE_KEY_AES,
39+
} mf_desfire_key_type_t;
40+
41+
typedef struct {
42+
uint8_t aid[3];
43+
} mf_desfire_aid_t;
44+
45+
typedef struct {
46+
uint8_t hw[7];
47+
uint8_t sw[7];
48+
uint8_t uid[7];
49+
uint8_t batch[7];
50+
} mf_desfire_version_t;
51+
52+
typedef struct {
53+
nfc_iso_dep_data_t dep;
54+
bool dep_ready;
55+
bool authenticated;
56+
bool ev2_authenticated;
57+
mf_desfire_key_type_t key_type;
58+
uint8_t key_no;
59+
uint8_t session_key[16];
60+
uint8_t iv[16];
61+
uint8_t ev2_ti[4];
62+
uint16_t ev2_cmd_ctr;
63+
uint8_t ev2_ses_mac[16];
64+
uint8_t ev2_ses_enc[16];
65+
uint8_t ev2_pd_cap2[6];
66+
uint8_t ev2_pcd_cap2[6];
67+
} mf_desfire_session_t;
68+
69+
hb_nfc_err_t mf_desfire_poller_init(const nfc_iso14443a_data_t* card,
70+
mf_desfire_session_t* session);
71+
72+
int mf_desfire_apdu_transceive(mf_desfire_session_t* session,
73+
const uint8_t* apdu,
74+
size_t apdu_len,
75+
uint8_t* rx,
76+
size_t rx_max,
77+
int timeout_ms);
78+
79+
hb_nfc_err_t mf_desfire_transceive_native(mf_desfire_session_t* session,
80+
uint8_t cmd,
81+
const uint8_t* data,
82+
size_t data_len,
83+
uint8_t* out,
84+
size_t out_max,
85+
size_t* out_len,
86+
uint16_t* sw);
87+
88+
hb_nfc_err_t mf_desfire_get_version(mf_desfire_session_t* session,
89+
mf_desfire_version_t* out);
90+
91+
hb_nfc_err_t mf_desfire_select_application(mf_desfire_session_t* session,
92+
const mf_desfire_aid_t* aid);
93+
94+
hb_nfc_err_t mf_desfire_authenticate_ev1_3des(mf_desfire_session_t* session,
95+
uint8_t key_no,
96+
const uint8_t key[16]);
97+
98+
hb_nfc_err_t mf_desfire_authenticate_ev1_aes(mf_desfire_session_t* session,
99+
uint8_t key_no,
100+
const uint8_t key[16]);
101+
102+
hb_nfc_err_t mf_desfire_authenticate_ev2_first(mf_desfire_session_t* session,
103+
uint8_t key_no,
104+
const uint8_t key[16]);
105+
106+
hb_nfc_err_t mf_desfire_authenticate_ev2_nonfirst(mf_desfire_session_t* session,
107+
uint8_t key_no,
108+
const uint8_t key[16]);
109+
110+
hb_nfc_err_t mf_desfire_get_application_ids(mf_desfire_session_t* session,
111+
uint8_t* out,
112+
size_t out_max,
113+
size_t* out_len);
114+
115+
hb_nfc_err_t mf_desfire_get_file_ids(mf_desfire_session_t* session,
116+
uint8_t* out,
117+
size_t out_max,
118+
size_t* out_len);
119+
120+
hb_nfc_err_t mf_desfire_get_key_settings(mf_desfire_session_t* session,
121+
uint8_t* key_settings,
122+
uint8_t* max_keys);
123+
124+
hb_nfc_err_t mf_desfire_read_data(mf_desfire_session_t* session,
125+
uint8_t file_id,
126+
uint32_t offset,
127+
uint32_t length,
128+
uint8_t* out,
129+
size_t out_max,
130+
size_t* out_len);
131+
132+
hb_nfc_err_t mf_desfire_write_data(mf_desfire_session_t* session,
133+
uint8_t file_id,
134+
uint32_t offset,
135+
const uint8_t* data,
136+
size_t data_len);
137+
138+
hb_nfc_err_t mf_desfire_commit_transaction(mf_desfire_session_t* session);
139+
hb_nfc_err_t mf_desfire_abort_transaction(mf_desfire_session_t* session);
140+
141+
#ifdef __cplusplus
142+
}
143+
#endif
144+
145+
#endif /* MF_DESFIRE_H */
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @file mf_desfire_emu.h
3+
* @brief Minimal MIFARE DESFire (native) APDU emulation helpers.
4+
*/
5+
#ifndef MF_DESFIRE_EMU_H
6+
#define MF_DESFIRE_EMU_H
7+
8+
#include <stdint.h>
9+
#include <stdbool.h>
10+
11+
/** Reset DESFire emu session state. */
12+
void mf_desfire_emu_reset(void);
13+
14+
/**
15+
* Handle a DESFire native APDU (CLA=0x90).
16+
*
17+
* @param apdu input APDU buffer
18+
* @param apdu_len input length
19+
* @param out output buffer (data + SW1 SW2)
20+
* @param out_len output length
21+
* @return true if handled, false if not a DESFire APDU
22+
*/
23+
bool mf_desfire_emu_handle_apdu(const uint8_t* apdu, int apdu_len,
24+
uint8_t* out, int* out_len);
25+
26+
#endif /* MF_DESFIRE_EMU_H */

0 commit comments

Comments
 (0)