1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Common functionality for low/high-frequency GALLAGHER tag encoding & decoding.
17 //-----------------------------------------------------------------------------
25 #include "commonutil.h"
28 #include "mifaredefault.h"
31 #include "protocols.h"
33 #include "util_posix.h"
34 #include "cmdparser.h"
36 static int mfG4ExCommand(uint8_t cmd
, uint8_t *pwd
, uint8_t *data
, size_t datalen
, uint8_t *response
, size_t *responselen
, bool verbose
) {
43 memset(&payload
, 0, sizeof(payload
));
45 if (datalen
> sizeof(payload
.data
)) {
49 payload
.cmdheader
= 0xCF;
50 payload
.command
= cmd
;
53 memcpy(payload
.pwd
, pwd
, sizeof(payload
.pwd
));
56 if (data
!= NULL
&& datalen
> 0) {
57 memcpy(payload
.data
, data
, datalen
);
63 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_RAW
| ISO14A_NO_RATS
| ISO14A_APPEND_CRC
, 6 + datalen
, 0, (uint8_t *)&payload
, 6 + datalen
);
65 PacketResponseNG resp
;
66 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
67 if (resp
.oldarg
[0] != 2) {
68 if (verbose
) PrintAndLogEx(ERR
, "No card in the field.");
72 iso14a_card_select_t card
;
73 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
75 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
76 PrintAndLogEx(SUCCESS
, "ATQA: " _GREEN_("%02X %02X"), card
.atqa
[1], card
.atqa
[0]);
77 PrintAndLogEx(SUCCESS
, " SAK: " _GREEN_("%02X [%" PRIu64
"]"), card
.sak
, resp
.oldarg
[0]);
80 if (verbose
) PrintAndLogEx(ERR
, "No card in the field.");
84 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
85 resplen
= resp
.oldarg
[0];
88 if (verbose
) PrintAndLogEx(ERR
, "No card response.");
92 resplen
= resplen
- 2; // 14A CRC
97 if (verbose
) PrintAndLogEx(ERR
, "Buffer too small(%d).", resplen
);
101 if (response
!= NULL
)
102 memcpy(response
, resp
.data
.asBytes
, resplen
);
104 if (responselen
!= NULL
)
105 *responselen
= resplen
;
109 if (verbose
) PrintAndLogEx(ERR
, "Reply timeout.");
114 int mfG4GetConfig(uint8_t *pwd
, uint8_t *data
, size_t *datalen
, bool verbose
) {
115 uint8_t resp
[40] = {0};
118 int res
= mfG4ExCommand(GEN4_CMD_DUMP_CONFIG
, pwd
, NULL
, 0, resp
, &resplen
, verbose
);
119 if (res
!= PM3_SUCCESS
) {
124 memcpy(data
, resp
, resplen
);
127 if (datalen
!= NULL
) {
134 int mfG4GetFactoryTest(uint8_t *pwd
, uint8_t *data
, size_t *datalen
, bool verbose
) {
135 uint8_t resp
[40] = {0};
138 int res
= mfG4ExCommand(GEN4_CMD_FACTORY_TEST
, pwd
, NULL
, 0, resp
, &resplen
, verbose
);
139 if (res
!= PM3_SUCCESS
) {
144 memcpy(data
, resp
, resplen
);
147 if (datalen
!= NULL
) {
154 int mfG4ChangePassword(uint8_t *pwd
, uint8_t *newpwd
, bool verbose
) {
155 uint8_t resp
[40] = {0};
158 int res
= mfG4ExCommand(GEN4_CMD_CHANGE_PASSWORD
, pwd
, newpwd
, 4, resp
, &resplen
, verbose
);
159 if (res
!= PM3_SUCCESS
) {
163 if (resplen
!= 2 || resp
[0] != 0x90 || resp
[1] != 0x00) {
164 return PM3_EAPDU_FAIL
;
170 int mfG4GetBlock(uint8_t *pwd
, uint8_t blockno
, uint8_t *data
, uint8_t workFlags
) {
176 payload
.blockno
= blockno
;
177 memcpy(payload
.pwd
, pwd
, sizeof(payload
.pwd
));
178 payload
.workFlags
= workFlags
;
180 clearCommandBuffer();
181 SendCommandNG(CMD_HF_MIFARE_G4_RDBL
, (uint8_t *)&payload
, sizeof(payload
));
182 PacketResponseNG resp
;
183 if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL
, &resp
, 1500) == false) {
184 PrintAndLogEx(WARNING
, "command execution time out");
188 if (resp
.status
!= PM3_SUCCESS
) {
192 memcpy(data
, resp
.data
.asBytes
, MFBLOCK_SIZE
);
196 int mfG4SetBlock(uint8_t *pwd
, uint8_t blockno
, uint8_t *data
, uint8_t workFlags
) {
200 uint8_t data
[MFBLOCK_SIZE
];
203 payload
.blockno
= blockno
;
204 memcpy(payload
.pwd
, pwd
, sizeof(payload
.pwd
));
205 memcpy(payload
.data
, data
, sizeof(payload
.data
));
206 payload
.workFlags
= workFlags
;
208 clearCommandBuffer();
209 SendCommandNG(CMD_HF_MIFARE_G4_WRBL
, (uint8_t *)&payload
, sizeof(payload
));
210 PacketResponseNG resp
;
211 if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_WRBL
, &resp
, 1500) == false) {
212 PrintAndLogEx(WARNING
, "command execution time out");
216 if (resp
.status
!= PM3_SUCCESS
) {