recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / client / src / mifare / gen4.c
blob7487d127dc64663900f92cf33e9b8dd64ca12f95
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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 //-----------------------------------------------------------------------------
18 #include "gen4.h"
20 #include <inttypes.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "commonutil.h"
26 #include "util.h"
27 #include "ui.h"
28 #include "mifaredefault.h"
29 #include "comms.h"
30 #include "cmdhf14a.h"
31 #include "protocols.h"
32 #include "mfkey.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) {
37 struct p {
38 uint8_t cmdheader;
39 uint8_t pwd[4];
40 uint8_t command;
41 uint8_t data[32];
42 } PACKED payload;
43 memset(&payload, 0, sizeof(payload));
45 if (datalen > sizeof(payload.data)) {
46 return PM3_EINVARG;
49 payload.cmdheader = 0xCF;
50 payload.command = cmd;
52 if (pwd != NULL) {
53 memcpy(payload.pwd, pwd, sizeof(payload.pwd));
56 if (data != NULL && datalen > 0) {
57 memcpy(payload.data, data, datalen);
60 int resplen = 0;
62 clearCommandBuffer();
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.");
69 return PM3_ETIMEOUT;
72 iso14a_card_select_t card;
73 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
74 if (verbose) {
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]);
79 } else {
80 if (verbose) PrintAndLogEx(ERR, "No card in the field.");
81 return PM3_ETIMEOUT;
84 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
85 resplen = resp.oldarg[0];
87 if (!resplen) {
88 if (verbose) PrintAndLogEx(ERR, "No card response.");
89 return PM3_EFAILED;
92 resplen = resplen - 2; // 14A CRC
93 if (resplen < 0)
94 resplen = 0;
96 if (resplen > 40) {
97 if (verbose) PrintAndLogEx(ERR, "Buffer too small(%d).", resplen);
98 return PM3_EOVFLOW;
101 if (response != NULL)
102 memcpy(response, resp.data.asBytes, resplen);
104 if (responselen != NULL)
105 *responselen = resplen;
107 return PM3_SUCCESS;
108 } else {
109 if (verbose) PrintAndLogEx(ERR, "Reply timeout.");
110 return PM3_ETIMEOUT;
114 int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
115 uint8_t resp[40] = {0};
116 size_t resplen = 0;
118 int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose);
119 if (res != PM3_SUCCESS) {
120 return res;
123 if (data != NULL) {
124 memcpy(data, resp, resplen);
127 if (datalen != NULL) {
128 *datalen = resplen;
131 return PM3_SUCCESS;
134 int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
135 uint8_t resp[40] = {0};
136 size_t resplen = 0;
138 int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose);
139 if (res != PM3_SUCCESS) {
140 return res;
143 if (data != NULL) {
144 memcpy(data, resp, resplen);
147 if (datalen != NULL) {
148 *datalen = resplen;
151 return PM3_SUCCESS;
154 int mfG4ChangePassword(uint8_t *pwd, uint8_t *newpwd, bool verbose) {
155 uint8_t resp[40] = {0};
156 size_t resplen = 0;
158 int res = mfG4ExCommand(GEN4_CMD_CHANGE_PASSWORD, pwd, newpwd, 4, resp, &resplen, verbose);
159 if (res != PM3_SUCCESS) {
160 return res;
163 if (resplen != 2 || resp[0] != 0x90 || resp[1] != 0x00) {
164 return PM3_EAPDU_FAIL;
167 return PM3_SUCCESS;
170 int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
171 struct p {
172 uint8_t blockno;
173 uint8_t pwd[4];
174 uint8_t workFlags;
175 } PACKED payload;
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");
185 return PM3_ETIMEOUT;
188 if (resp.status != PM3_SUCCESS) {
189 return PM3_EUNDEF;
192 memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
193 return PM3_SUCCESS;
196 int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
197 struct p {
198 uint8_t blockno;
199 uint8_t pwd[4];
200 uint8_t data[MFBLOCK_SIZE];
201 uint8_t workFlags;
202 } PACKED payload;
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");
213 return PM3_ETIMEOUT;
216 if (resp.status != PM3_SUCCESS) {
217 return PM3_EUNDEF;
220 return PM3_SUCCESS;