fix return codes

This commit is contained in:
iceman1001 2024-01-31 21:44:23 +01:00
commit 33380ad240
5 changed files with 231 additions and 111 deletions

View file

@ -923,14 +923,16 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
// select with no disconnect and set gs_frame_len // select with no disconnect and set gs_frame_len
int selres = SelectCard14443A_4(false, !silentMode, NULL); int selres = SelectCard14443A_4(false, !silentMode, NULL);
gs_frames_num = 0; gs_frames_num = 0;
if (selres != PM3_SUCCESS) if (selres != PM3_SUCCESS) {
return selres; return selres;
}
} }
if (leaveSignalON) if (leaveSignalON) {
cmdc |= ISO14A_NO_DISCONNECT; cmdc |= ISO14A_NO_DISCONNECT;
}
uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | gs_frames_num, 0x00}; uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | gs_frames_num, 0x00 };
gs_frames_num ^= 1; gs_frames_num ^= 1;
int min = MIN((PM3_CMD_DATA_SIZE - 2), (datainlen & 0x1FF)); int min = MIN((PM3_CMD_DATA_SIZE - 2), (datainlen & 0x1FF));
@ -939,44 +941,54 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
uint8_t *recv; uint8_t *recv;
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
recv = resp.data.asBytes; recv = resp.data.asBytes;
int iLen = resp.oldarg[0]; int iLen = resp.oldarg[0];
if (!iLen) { if (iLen == 0) {
if (!silentMode) PrintAndLogEx(ERR, "No card response."); if (silentMode == false) {
return 1; PrintAndLogEx(ERR, "No card response");
}
return PM3_ECARDEXCHANGE;
} }
*dataoutlen = iLen - 2; *dataoutlen = iLen - 2;
if (*dataoutlen < 0) if (*dataoutlen < 0) {
*dataoutlen = 0; *dataoutlen = 0;
}
if (maxdataoutlen && *dataoutlen > maxdataoutlen) { if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
if (!silentMode) PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); if (silentMode == false) {
return 2; PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
}
return PM3_ELENGTH;
} }
if (recv[0] != data[0]) { if (recv[0] != data[0]) {
if (!silentMode) PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", recv[0], data[0]); if (silentMode == false) {
return 2; PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", recv[0], data[0]);
}
return PM3_ELENGTH;
} }
memcpy(dataout, &recv[2], *dataoutlen); memcpy(dataout, &recv[2], *dataoutlen);
// CRC Check // CRC Check
if (iLen == -1) { if (iLen == -1) {
if (!silentMode) PrintAndLogEx(ERR, "ISO 14443A CRC error."); if (silentMode == false) {
return 3; PrintAndLogEx(ERR, "ISO 14443A CRC error.");
}
return PM3_ECRC;
} }
} else { } else {
if (!silentMode) PrintAndLogEx(ERR, "Reply timeout."); if (silentMode == false) {
return 4; PrintAndLogEx(ERR, "Reply timeout.");
}
return PM3_ETIMEOUT;
} }
return 0; return PM3_SUCCESS;
} }
int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters) { int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters) {

View file

@ -382,6 +382,12 @@ static int CmdHFMFPInfo(const char *Cmd) {
uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00};
int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false); int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false);
if (res != PM3_SUCCESS) {
PrintAndLogEx(INFO, "identification failed");
PrintAndLogEx(NORMAL, "");
DropField();
return PM3_SUCCESS;
}
// DESFire answers 0x1C or 67 00 // DESFire answers 0x1C or 67 00
// Plus answers 0x0B, 0x09, 0x06 // Plus answers 0x0B, 0x09, 0x06
// 6D00 is "INS code not supported" in APDU // 6D00 is "INS code not supported" in APDU
@ -413,12 +419,14 @@ static int CmdHFMFPInfo(const char *Cmd) {
PrintAndLogEx(INFO, " result.... " _GREEN_("MIFARE Plus SL0/SL3")); PrintAndLogEx(INFO, " result.... " _GREEN_("MIFARE Plus SL0/SL3"));
} }
if (!res && datalen > 1 && data[0] == 0x09) { if ((datalen > 1) &&
(data[0] == 0x09)) {
SLmode = 0; SLmode = 0;
} }
} }
} }
if (isPlus) { if (isPlus) {
// How do we detect SL0 / SL1 / SL2 / SL3 modes?!? // How do we detect SL0 / SL1 / SL2 / SL3 modes?!?
PrintAndLogEx(INFO, "--- " _CYAN_("Security Level (SL)")); PrintAndLogEx(INFO, "--- " _CYAN_("Security Level (SL)"));
@ -446,7 +454,7 @@ static int CmdHFMFPInfo(const char *Cmd) {
} }
} }
} else { } else {
PrintAndLogEx(INFO, "\tMifare Plus info not available."); PrintAndLogEx(INFO, " Mifare Plus info not available");
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
DropField(); DropField();
@ -1730,7 +1738,6 @@ static int CmdHFMFPDump(const char *Cmd) {
*/ */
} }
static int CmdHFMFPMAD(const char *Cmd) { static int CmdHFMFPMAD(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;

View file

@ -495,53 +495,68 @@ static int DESFIRESendApdu(bool activate_field, sAPDU_t apdu, uint8_t *result, u
static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) { static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) {
*result_len = 0; *result_len = 0;
if (respcode) *respcode = 0xff; if (respcode) {
*respcode = 0xff;
}
if (activate_field) { if (activate_field) {
DropField(); DropField();
msleep(50); msleep(50);
} }
if (GetAPDULogging()) if (GetAPDULogging()) {
PrintAndLogEx(SUCCESS, "raw>> %s", sprint_hex(data, datalen)); PrintAndLogEx(SUCCESS, "raw>> %s", sprint_hex(data, datalen));
}
int res = ExchangeRAW14a(data, datalen, activate_field, true, result, max_result_len, (int *)result_len, true); int res = ExchangeRAW14a(data, datalen, activate_field, true, result, max_result_len, (int *)result_len, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
return res; return res;
} }
if (GetAPDULogging()) if (GetAPDULogging()) {
PrintAndLogEx(SUCCESS, "raw<< %s", sprint_hex(result, *result_len)); PrintAndLogEx(SUCCESS, "raw<< %s", sprint_hex(result, *result_len));
}
if (*result_len < 1) { if (*result_len < 1) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
*result_len -= 1 + 2; *result_len -= (1 + 2);
uint8_t rcode = result[0]; uint8_t rcode = result[0];
if (respcode) *respcode = rcode; if (respcode) {
*respcode = rcode;
}
memmove(&result[0], &result[1], *result_len); memmove(&result[0], &result[1], *result_len);
if (rcode != MFDES_S_OPERATION_OK && if (rcode != MFDES_S_OPERATION_OK &&
rcode != MFDES_S_SIGNATURE && rcode != MFDES_S_SIGNATURE &&
rcode != MFDES_S_ADDITIONAL_FRAME && rcode != MFDES_S_ADDITIONAL_FRAME &&
rcode != MFDES_S_NO_CHANGES) { rcode != MFDES_S_NO_CHANGES) {
if (GetAPDULogging())
if (GetAPDULogging()) {
PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode);
}
return PM3_EAPDU_FAIL; return PM3_EAPDU_FAIL;
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
if (resplen) if (resplen) {
*resplen = 0; *resplen = 0;
if (respcode) }
if (respcode) {
*respcode = 0xff; *respcode = 0xff;
}
uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1); uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1);
if (buf == NULL) if (buf == NULL) {
return PM3_EMALLOC; return PM3_EMALLOC;
}
uint32_t buflen = 0; uint32_t buflen = 0;
uint32_t pos = 0; uint32_t pos = 0;
uint32_t i = 1; uint32_t i = 1;
@ -558,7 +573,8 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
// tx chaining // tx chaining
size_t sentdatalen = 0; size_t sentdatalen = 0;
while (cdatalen >= sentdatalen) { while (cdatalen >= sentdatalen) {
if (cdatalen - sentdatalen > DESFIRE_TX_FRAME_MAX_LEN)
if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN)
len = DESFIRE_TX_FRAME_MAX_LEN; len = DESFIRE_TX_FRAME_MAX_LEN;
else else
len = cdatalen - sentdatalen; len = cdatalen - sentdatalen;
@ -580,9 +596,10 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
} }
sentdatalen += len; sentdatalen += len;
if (rcode != MFDES_ADDITIONAL_FRAME || buflen > 0) { if ((rcode != MFDES_ADDITIONAL_FRAME) || (buflen > 0)) {
if (sentdatalen != cdatalen) if (sentdatalen != cdatalen) {
PrintAndLogEx(WARNING, "Tx chaining error. Needs to send: %d but sent: %zu", cdatalen, sentdatalen); PrintAndLogEx(WARNING, "Tx chaining error. Needs to send: %d but sent: %zu", cdatalen, sentdatalen);
}
break; break;
} }
} }
@ -596,15 +613,19 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
memcpy(resp, buf, buflen); memcpy(resp, buf, buflen);
} }
} }
if (respcode != NULL) if (respcode != NULL) {
*respcode = rcode; *respcode = rcode;
}
pos += buflen; pos += buflen;
if (!enable_chaining) {
if (enable_chaining == false) {
if (rcode == MFDES_S_OPERATION_OK || if (rcode == MFDES_S_OPERATION_OK ||
rcode == MFDES_ADDITIONAL_FRAME) { rcode == MFDES_ADDITIONAL_FRAME) {
if (resplen)
if (resplen) {
*resplen = pos; *resplen = pos;
}
} }
free(buf); free(buf);
return PM3_SUCCESS; return PM3_SUCCESS;
@ -620,8 +641,9 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
return res; return res;
} }
if (respcode != NULL) if (respcode != NULL) {
*respcode = rcode; *respcode = rcode;
}
if (resp != NULL) { if (resp != NULL) {
if (splitbysize) { if (splitbysize) {
@ -634,22 +656,26 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
} }
pos += buflen; pos += buflen;
if (rcode != MFDES_ADDITIONAL_FRAME) break; if (rcode != MFDES_ADDITIONAL_FRAME)
break;
} }
if (resplen) if (resplen) {
*resplen = (splitbysize) ? i : pos; *resplen = (splitbysize) ? i : pos;
}
free(buf); free(buf);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
if (resplen) if (resplen) {
*resplen = 0; *resplen = 0;
}
if (respcode) if (respcode) {
*respcode = 0xff; *respcode = 0xff;
}
uint16_t sw = 0; uint16_t sw = 0;
uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1); uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1);
@ -679,8 +705,9 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
apdu.data = &data[sentdatalen]; apdu.data = &data[sentdatalen];
if (sentdatalen > 0) if (sentdatalen > 0) {
apdu.INS = MFDES_ADDITIONAL_FRAME; apdu.INS = MFDES_ADDITIONAL_FRAME;
}
res = DESFIRESendApdu(activate_field, apdu, buf, DESFIRE_BUFFER_SIZE, &buflen, &sw); res = DESFIRESendApdu(activate_field, apdu, buf, DESFIRE_BUFFER_SIZE, &buflen, &sw);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
@ -691,14 +718,16 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
sentdatalen += apdu.Lc; sentdatalen += apdu.Lc;
if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME) || buflen > 0) { if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME) || buflen > 0) {
if (sentdatalen != datalen) if (sentdatalen != datalen) {
PrintAndLogEx(WARNING, "Tx chaining error. Needs to send: %zu but sent: %zu", datalen, sentdatalen); PrintAndLogEx(WARNING, "Tx chaining error. Needs to send: %zu but sent: %zu", datalen, sentdatalen);
}
break; break;
} }
} }
if (respcode != NULL && ((sw & 0xff00) == 0x9100)) if (respcode != NULL && ((sw & 0xff00) == 0x9100)) {
*respcode = sw & 0xff; *respcode = sw & 0xff;
}
if (resp) { if (resp) {
if (splitbysize) { if (splitbysize) {
@ -710,11 +739,13 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
} }
pos += buflen; pos += buflen;
if (!enable_chaining) { if (enable_chaining == false) {
if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) || if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) ||
sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) {
if (resplen)
if (resplen) {
*resplen = pos; *resplen = pos;
}
} }
free(buf); free(buf);
return PM3_SUCCESS; return PM3_SUCCESS;
@ -735,8 +766,9 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
return res; return res;
} }
if (respcode != NULL && ((sw & 0xff00) == 0x9100)) if (respcode != NULL && ((sw & 0xff00) == 0x9100)) {
*respcode = sw & 0xff; *respcode = sw & 0xff;
}
if (resp != NULL) { if (resp != NULL) {
if (splitbysize) { if (splitbysize) {
@ -749,11 +781,14 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
} }
pos += buflen; pos += buflen;
if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) break; if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) {
break;
}
} }
if (resplen) if (resplen) {
*resplen = (splitbysize) ? i : pos; *resplen = (splitbysize) ? i : pos;
}
free(buf); free(buf);
return PM3_SUCCESS; return PM3_SUCCESS;
@ -761,13 +796,16 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
static int DesfireExchangeISO(bool activate_field, DesfireContext_t *ctx, sAPDU_t apdu, uint16_t le, uint8_t *resp, size_t *resplen, uint16_t *sw) { static int DesfireExchangeISO(bool activate_field, DesfireContext_t *ctx, sAPDU_t apdu, uint16_t le, uint8_t *resp, size_t *resplen, uint16_t *sw) {
uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1);
if (data == NULL) if (data == NULL) {
return PM3_EMALLOC; return PM3_EMALLOC;
}
uint32_t datalen = 0; uint32_t datalen = 0;
int res = DESFIRESendApduEx(activate_field, apdu, le, data, DESFIRE_BUFFER_SIZE, &datalen, sw); int res = DESFIRESendApduEx(activate_field, apdu, le, data, DESFIRE_BUFFER_SIZE, &datalen, sw);
if (res == PM3_SUCCESS) if (res == PM3_SUCCESS) {
DesfireSecureChannelDecode(ctx, data, datalen, 0, resp, resplen); DesfireSecureChannelDecode(ctx, data, datalen, 0, resp, resplen);
}
free(data); free(data);
return res; return res;
@ -791,15 +829,18 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount,
size_t tlen = len + blockdata[i * blockdatasize]; size_t tlen = len + blockdata[i * blockdatasize];
if (tlen > dstdatalen) { if (tlen > dstdatalen) {
tlen = dstdatalen; tlen = dstdatalen;
if (tlen >= len) if (tlen >= len)
blockdata[i * blockdatasize] = tlen - len; blockdata[i * blockdatasize] = tlen - len;
else else
blockdata[i * blockdatasize] = 0; blockdata[i * blockdatasize] = 0;
} }
if (len == tlen) { if (len == tlen) {
*blockdatacount = i; *blockdatacount = i;
break; break;
} }
memcpy(&blockdata[i * blockdatasize + 1], &dstdata[len], tlen - len); memcpy(&blockdata[i * blockdatasize + 1], &dstdata[len], tlen - len);
len = tlen; len = tlen;
} }
@ -809,12 +850,15 @@ int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, u
uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
int res = PM3_SUCCESS; int res = PM3_SUCCESS;
if (!PrintChannelModeWarning(cmd, ctx->secureChannel, ctx->cmdSet, ctx->commMode)) if (PrintChannelModeWarning(cmd, ctx->secureChannel, ctx->cmdSet, ctx->commMode) == false) {
DesfirePrintContext(ctx); DesfirePrintContext(ctx);
}
uint8_t *databuf = calloc(DESFIRE_BUFFER_SIZE, 1); uint8_t *databuf = calloc(DESFIRE_BUFFER_SIZE, 1);
if (databuf == NULL) if (databuf == NULL) {
return PM3_EMALLOC; return PM3_EMALLOC;
}
size_t databuflen = 0; size_t databuflen = 0;
switch (ctx->cmdSet) { switch (ctx->cmdSet) {
@ -857,13 +901,16 @@ int DesfireExchange(DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t da
} }
int DesfireSelectAID(DesfireContext_t *ctx, uint8_t *aid1, uint8_t *aid2) { int DesfireSelectAID(DesfireContext_t *ctx, uint8_t *aid1, uint8_t *aid2) {
if (aid1 == NULL) if (aid1 == NULL) {
return PM3_EINVARG; return PM3_EINVARG;
}
uint8_t data[6] = {0}; uint8_t data[6] = {0};
memcpy(data, aid1, 3); memcpy(data, aid1, 3);
if (aid2 != NULL) if (aid2 != NULL) {
memcpy(&data[3], aid2, 3); memcpy(&data[3], aid2, 3);
}
uint8_t resp[257] = {0}; uint8_t resp[257] = {0};
size_t resplen = 0; size_t resplen = 0;
uint8_t respcode = 0; uint8_t respcode = 0;
@ -871,12 +918,14 @@ int DesfireSelectAID(DesfireContext_t *ctx, uint8_t *aid1, uint8_t *aid2) {
ctx->secureChannel = DACNone; ctx->secureChannel = DACNone;
int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0); int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
if (resplen != 0) if (resplen != 0) {
return PM3_ECARDEXCHANGE; return PM3_ECARDEXCHANGE;
}
// select operation fail // select operation fail
if (respcode != MFDES_S_OPERATION_OK) if (respcode != MFDES_S_OPERATION_OK) {
return PM3_EAPDU_FAIL; return PM3_EAPDU_FAIL;
}
DesfireClearSession(ctx); DesfireClearSession(ctx);
ctx->appSelected = (aid1[0] != 0x00 || aid1[1] != 0x00 || aid1[2] != 0x00); ctx->appSelected = (aid1[0] != 0x00 || aid1[1] != 0x00 || aid1[2] != 0x00);
@ -1933,8 +1982,9 @@ int DesfireGetFreeMem(DesfireContext_t *dctx, uint32_t *freemem) {
uint8_t resp[257] = {0}; uint8_t resp[257] = {0};
size_t resplen = 0; size_t resplen = 0;
int res = DesfireCommandRxData(dctx, MFDES_GET_FREE_MEMORY, resp, &resplen, 3); int res = DesfireCommandRxData(dctx, MFDES_GET_FREE_MEMORY, resp, &resplen, 3);
if (res == PM3_SUCCESS) if (res == PM3_SUCCESS) {
*freemem = DesfireAIDByteToUint(resp); *freemem = DesfireAIDByteToUint(resp);
}
return res; return res;
} }
@ -2148,8 +2198,9 @@ int DesfireValueFileOperations(DesfireContext_t *dctx, uint8_t fid, uint8_t oper
int res = DesfireCommand(dctx, operation, data, datalen, resp, &resplen, -1); int res = DesfireCommand(dctx, operation, data, datalen, resp, &resplen, -1);
if (resplen == 4 && value) if (resplen == 4 && value) {
*value = MemLeToUint4byte(resp); *value = MemLeToUint4byte(resp);
}
return res; return res;
} }

View file

@ -218,14 +218,20 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode); int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode);
if (res) { if (res != PM3_SUCCESS) {
if (!silentMode) PrintAndLogEx(ERR, "Exchange raw error: %d", res); if (silentMode == false) {
if (dropFieldIfError) DropField(); PrintAndLogEx(ERR, "Exchange raw error: %d", res);
}
if (dropFieldIfError) {
DropField();
}
return PM3_ERFTRANS; return PM3_ERFTRANS;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "<phase1: %s", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "< phase1: %s", sprint_hex(data, datalen));
}
if (datalen < 1) { if (datalen < 1) {
if (!silentMode) PrintAndLogEx(ERR, "Card response wrong length: %d", datalen); if (!silentMode) PrintAndLogEx(ERR, "Card response wrong length: %d", datalen);
@ -247,8 +253,9 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
aes_decode(NULL, key, &data[1], RndB, 16); aes_decode(NULL, key, &data[1], RndB, 16);
RndB[16] = RndB[0]; RndB[16] = RndB[0];
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "RndB: %s", sprint_hex(RndB, 16)); PrintAndLogEx(INFO, "RndB: %s", sprint_hex(RndB, 16));
}
uint8_t cmd2[33] = {0}; uint8_t cmd2[33] = {0};
cmd2[0] = 0x72; cmd2[0] = 0x72;
@ -262,14 +269,19 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33)); PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
} }
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode); res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode);
if (res) { if (res != PM3_SUCCESS) {
if (!silentMode) PrintAndLogEx(ERR, "Exchange raw error: %d", res); if (silentMode == false) {
if (dropFieldIfError) DropField(); PrintAndLogEx(ERR, "Exchange raw error: %d", res);
}
if (dropFieldIfError) {
DropField();
}
return PM3_ERFTRANS; return PM3_ERFTRANS;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "<phase2: %s", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "< phase2: %s", sprint_hex(data, datalen));
}
aes_decode(NULL, key, &data[1], raw, 32); aes_decode(NULL, key, &data[1], raw, 32);
@ -320,11 +332,13 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
PrintAndLogEx(INFO, "kmac: %s", sprint_hex(kmac, 16)); PrintAndLogEx(INFO, "kmac: %s", sprint_hex(kmac, 16));
} }
if (!leaveSignalON) if (leaveSignalON == false) {
DropField(); DropField();
}
if (verbose) if (verbose) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
}
if (mf4session) { if (mf4session) {
mf4session->Authenticated = true; mf4session->Authenticated = true;
@ -341,21 +355,23 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti
memmove(mf4session->Kmac, kmac, 16); memmove(mf4session->Kmac, kmac, 16);
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Authentication OK"); PrintAndLogEx(INFO, "Authentication OK");
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { static int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
if (g_verbose_mode) if (g_verbose_mode) {
PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen));
}
int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen, false); int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen, false);
if (g_verbose_mode) if (g_verbose_mode) {
PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen));
}
return res; return res;
} }
@ -373,48 +389,79 @@ int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int
} }
int MFPReadBlock(mf4Session_t *mf4session, bool plain, bool nomaccmd, bool nomacres, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { int MFPReadBlock(mf4Session_t *mf4session, bool plain, bool nomaccmd, bool nomacres, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
int cmdb = 0x31; int cmdb = 0x31;
if (nomacres) {cmdb = cmdb ^ 0x01;} // If we do not want MAC in reply, remove 0x01 if (nomacres) {
if (plain) {cmdb = cmdb ^ 0x02;} // If we do not need an encrypted transmission, add 0x02 cmdb = cmdb ^ 0x01; // If we do not want MAC in reply, remove 0x01
if (nomaccmd) {cmdb = cmdb ^ 0x04;} // If we do not want to send a MAC, remove 0x04 }
if (plain) {
cmdb = cmdb ^ 0x02; // If we do not need an encrypted transmission, add 0x02
}
if (nomaccmd) {
cmdb = cmdb ^ 0x04; // If we do not want to send a MAC, remove 0x04
}
uint8_t rcmd1[4] = {cmdb, blockNum, 0x00, blockCount}; uint8_t rcmd1[4] = {cmdb, blockNum, 0x00, blockCount};
uint8_t maccmddat[8] = {0}; uint8_t maccmddat[8] = {0};
uint8_t rcmd[nomaccmd ? 4 : 12]; uint8_t rcmd[nomaccmd ? 4 : 12];
if (!nomaccmd && mf4session)
CalculateMAC(mf4session, mtypReadCmd, blockNum, blockCount, rcmd1, 4, &maccmddat[0], g_verbose_mode);
memmove(rcmd, rcmd1, 4);
if (!nomaccmd) {memmove(&rcmd[4], maccmddat, 8);}
int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if (res)
return res;
if (mf4session)
mf4session->R_Ctr++;
if (mf4session && !nomacres && *dataoutlen > 11)
CalculateMAC(mf4session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, g_verbose_mode);
return 0; if (nomaccmd == false && mf4session) {
CalculateMAC(mf4session, mtypReadCmd, blockNum, blockCount, rcmd1, 4, &maccmddat[0], g_verbose_mode);
}
memmove(rcmd, rcmd1, 4);
if (nomaccmd == false) {
memmove(&rcmd[4], maccmddat, 8);
}
int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if (res != PM3_SUCCESS) {
return res;
}
if (mf4session) {
mf4session->R_Ctr++;
}
if (mf4session && !nomacres && *dataoutlen > 11) {
CalculateMAC(mf4session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, g_verbose_mode);
}
return PM3_SUCCESS;
} }
int MFPWriteBlock(mf4Session_t *mf4session, bool plain, bool nomacres, uint8_t blockNum, uint8_t blockHdr, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { int MFPWriteBlock(mf4Session_t *mf4session, bool plain, bool nomacres, uint8_t blockNum, uint8_t blockHdr, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
int cmdb = 0xA1; int cmdb = 0xA1;
if (nomacres) {cmdb = cmdb ^ 0x01;} // If we do not want MAC in reply, remove 0x01 if (nomacres) {
if (plain) {cmdb = cmdb ^ 0x02;} // If we do not need an encrypted transmission, add 0x02 cmdb = cmdb ^ 0x01; // If we do not want MAC in reply, remove 0x01
}
if (plain) {
cmdb = cmdb ^ 0x02; // If we do not need an encrypted transmission, add 0x02
}
uint8_t rcmd[1 + 2 + 16 + 8] = {cmdb, blockNum, blockHdr}; uint8_t rcmd[1 + 2 + 16 + 8] = {cmdb, blockNum, blockHdr};
memmove(&rcmd[3], data, 16); memmove(&rcmd[3], data, 16);
if (mf4session) if (mf4session) {
CalculateMAC(mf4session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], g_verbose_mode); CalculateMAC(mf4session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], g_verbose_mode);
}
int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if (res) if (res != PM3_SUCCESS) {
return res; return res;
}
if (mf4session) if (mf4session) {
mf4session->W_Ctr++; mf4session->W_Ctr++;
}
if (mf4session && mac && *dataoutlen > 3 && !nomacres) if (mf4session && mac && *dataoutlen > 3 && !nomacres) {
CalculateMAC(mf4session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, g_verbose_mode); CalculateMAC(mf4session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, g_verbose_mode);
}
return 0; return PM3_SUCCESS;
} }
int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose) { int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose) {
@ -424,8 +471,9 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data
uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0); uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0);
keyn[0] = uKeyNum >> 8; keyn[0] = uKeyNum >> 8;
keyn[1] = uKeyNum & 0xff; keyn[1] = uKeyNum & 0xff;
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "--sector[%u]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); PrintAndLogEx(INFO, "--sector[%u]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum);
}
mf4Session_t _session; mf4Session_t _session;
int res = MifareAuth4(&_session, keyn, key, true, true, true, verbose, false); int res = MifareAuth4(&_session, keyn, key, true, true, true, verbose, false);
@ -467,16 +515,18 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8));
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
if (!verbose) if (verbose == false) {
return 7; return 7;
}
} else { } else {
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8));
}
} }
} }
DropField(); DropField();
return 0; return PM3_SUCCESS;
} }
int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
@ -501,13 +551,13 @@ int MFPGetVersion(bool activateField, bool leaveSignalON, uint8_t *dataout, int
if (tmp[0] == 0xAF) { if (tmp[0] == 0xAF) {
c[0] = 0xAF; c[0] = 0xAF;
res = intExchangeRAW14aPlus(c, sizeof(c), false, true, tmp, maxdataoutlen, dataoutlen); res = intExchangeRAW14aPlus(c, sizeof(c), false, true, tmp, maxdataoutlen, dataoutlen);
if (res == 0) { if (res == PM3_SUCCESS) {
memcpy(dataout + 7, tmp + 1, (*dataoutlen - 3)); memcpy(dataout + 7, tmp + 1, (*dataoutlen - 3));
// MFDES_ADDITIONAL_FRAME // MFDES_ADDITIONAL_FRAME
res = intExchangeRAW14aPlus(c, sizeof(c), false, false, tmp, maxdataoutlen, dataoutlen); res = intExchangeRAW14aPlus(c, sizeof(c), false, false, tmp, maxdataoutlen, dataoutlen);
if (res == 0) { if (res == PM3_SUCCESS) {
if (tmp[0] == 0x90) { if (tmp[0] == 0x90) {
memcpy(dataout + 7 + 7, tmp + 1, (*dataoutlen - 3)); memcpy(dataout + 7 + 7, tmp + 1, (*dataoutlen - 3));
*dataoutlen = 28; *dataoutlen = 28;

View file

@ -232,9 +232,9 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
PacketResponseNG resp; PacketResponseNG resp;
uint32_t timeout = 0; uint32_t timeout = 0;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx((timeout == 0) ? INFO : NORMAL, "." NOLF); PrintAndLogEx((timeout) ? NORMAL : INFO, "." NOLF);
fflush(stdout); fflush(stdout);
timeout++; timeout++;