mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
fix #2384 the use of free() is completely wrong as we use bigbuff allocations. Converted the old style to new and removed the dynamic allocation.
This commit is contained in:
parent
2b276cae1a
commit
498af46fbf
1 changed files with 67 additions and 44 deletions
|
@ -543,30 +543,35 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
|
|
||||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
|
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
|
||||||
void *res = data;
|
void *res = data;
|
||||||
void *edata = NULL;
|
|
||||||
uint8_t first_cmac_byte = 0x00;
|
uint8_t first_cmac_byte = 0x00;
|
||||||
|
|
||||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||||
|
|
||||||
if (!key)
|
if (!key) {
|
||||||
return data;
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
// Return directly if we just have a status code.
|
// Return directly if we just have a status code.
|
||||||
if (1 == *nbytes)
|
if (1 == *nbytes) {
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
switch (communication_settings & MDCM_MASK) {
|
switch (communication_settings & MDCM_MASK) {
|
||||||
case MDCM_PLAIN:
|
case MDCM_PLAIN: {
|
||||||
|
|
||||||
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
|
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* pass through */
|
/* pass through */
|
||||||
case MDCM_MACED:
|
case MDCM_MACED: {
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
if (communication_settings & MAC_VERIFY) {
|
|
||||||
|
if ((communication_settings & MAC_VERIFY) == MAC_VERIFY) {
|
||||||
|
|
||||||
*nbytes -= key_macing_length(key);
|
*nbytes -= key_macing_length(key);
|
||||||
|
|
||||||
if (*nbytes == 0) {
|
if (*nbytes == 0) {
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
@ -577,18 +582,17 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
|
size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
|
||||||
edata = BigBuf_malloc(edl);
|
uint8_t edata[edl];
|
||||||
|
memset(edata, 0, sizeof(edata));
|
||||||
memcpy(edata, data, *nbytes - 1);
|
memcpy(edata, data, *nbytes - 1);
|
||||||
memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
|
|
||||||
|
|
||||||
mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
|
mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
|
||||||
|
|
||||||
if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
|
if (0 != memcmp((uint8_t *)data + *nbytes - 1, edata + edl - 8, 4)) {
|
||||||
#ifdef WITH_DEBUG
|
#ifdef WITH_DEBUG
|
||||||
Dbprintf("MACing not verified");
|
Dbprintf("MACing not verified");
|
||||||
hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
|
hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
|
||||||
hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
|
hexdump(edata + edl - 8, key_macing_length(key), "Actual ", 0);
|
||||||
#endif
|
#endif
|
||||||
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
|
@ -596,10 +600,16 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
if (!(communication_settings & CMAC_COMMAND))
|
case AS_NEW: {
|
||||||
|
|
||||||
|
if ((communication_settings & CMAC_COMMAND) != CMAC_COMMAND) {
|
||||||
break;
|
break;
|
||||||
if (communication_settings & CMAC_VERIFY) {
|
}
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if ((communication_settings & CMAC_VERIFY) == CMAC_VERIFY) {
|
||||||
if (*nbytes < 9) {
|
if (*nbytes < 9) {
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
@ -607,13 +617,16 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
}
|
}
|
||||||
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
|
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
|
||||||
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
|
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
|
||||||
|
|
||||||
|
n = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
|
|
||||||
cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
|
cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
|
||||||
|
|
||||||
if (communication_settings & CMAC_VERIFY) {
|
if ((communication_settings & CMAC_VERIFY) == CMAC_VERIFY) {
|
||||||
|
|
||||||
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
|
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
|
||||||
|
|
||||||
if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
|
if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
|
||||||
#ifdef WITH_DEBUG
|
#ifdef WITH_DEBUG
|
||||||
Dbprintf("CMAC NOT verified :-(");
|
Dbprintf("CMAC NOT verified :-(");
|
||||||
|
@ -628,12 +641,11 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(edata);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MDCM_ENCIPHERED:
|
}
|
||||||
|
case MDCM_ENCIPHERED: {
|
||||||
(*nbytes)--;
|
(*nbytes)--;
|
||||||
bool verified = false;
|
bool verified = false;
|
||||||
int crc_pos = 0x00;
|
int crc_pos = 0x00;
|
||||||
|
@ -670,48 +682,50 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
* verified, and accumulating 0's in it should not change it.
|
* verified, and accumulating 0's in it should not change it.
|
||||||
*/
|
*/
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
|
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
|
||||||
if (crc_pos < 0) {
|
if (crc_pos < 0) {
|
||||||
/* Single block */
|
crc_pos = 0; // Single block
|
||||||
crc_pos = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
/* Move status between payload and CRC */
|
/* Move status between payload and CRC */
|
||||||
res = DESFIRE(tag)->crypto_buffer;
|
res = DESFIRE(tag)->crypto_buffer;
|
||||||
memcpy(res, data, *nbytes);
|
memcpy(res, data, *nbytes);
|
||||||
|
|
||||||
crc_pos = (*nbytes) - 16 - 3;
|
crc_pos = (*nbytes) - 16 - 3;
|
||||||
if (crc_pos < 0) {
|
if (crc_pos < 0) {
|
||||||
/* Single block */
|
crc_pos = 0; // Single block
|
||||||
crc_pos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
|
memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
|
||||||
((uint8_t *)res)[crc_pos] = 0x00;
|
((uint8_t *)res)[crc_pos] = 0x00;
|
||||||
crc_pos++;
|
crc_pos++;
|
||||||
*nbytes += 1;
|
*nbytes += 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
uint16_t crc_16 = 0x00;
|
uint16_t crc_16 = 0x00;
|
||||||
uint32_t crc = 0x00;
|
uint32_t crc = 0x00;
|
||||||
|
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
AddCrc14A((uint8_t *)res, end_crc_pos);
|
AddCrc14A((uint8_t *)res, end_crc_pos);
|
||||||
end_crc_pos = crc_pos + 2;
|
end_crc_pos = crc_pos + 2;
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
crc = crc_16;
|
crc = crc_16;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
end_crc_pos = crc_pos + 4;
|
end_crc_pos = crc_pos + 4;
|
||||||
crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
|
crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!crc) {
|
|
||||||
|
if (crc == 0) {
|
||||||
verified = true;
|
verified = true;
|
||||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||||
uint8_t byte = ((uint8_t *)res)[n];
|
uint8_t byte = ((uint8_t *)res)[n];
|
||||||
|
@ -719,31 +733,40 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
verified = false;
|
verified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verified) {
|
if (verified) {
|
||||||
|
|
||||||
*nbytes = crc_pos;
|
*nbytes = crc_pos;
|
||||||
|
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
/* The status byte was already before the CRC */
|
/* The status byte was already before the CRC */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
x = ((uint8_t *)res)[crc_pos - 1];
|
x = ((uint8_t *)res)[crc_pos - 1];
|
||||||
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
|
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
|
||||||
((uint8_t *)res)[crc_pos] = x;
|
((uint8_t *)res)[crc_pos] = x;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
crc_pos++;
|
crc_pos++;
|
||||||
}
|
}
|
||||||
} while (!verified && (end_crc_pos < *nbytes));
|
|
||||||
|
|
||||||
if (!verified) {
|
} while (verified == false && (end_crc_pos < *nbytes));
|
||||||
|
|
||||||
|
if (verified == false) {
|
||||||
#ifdef WITH_DEBUG
|
#ifdef WITH_DEBUG
|
||||||
/* FIXME In some configurations, the file is transmitted PLAIN */
|
/* FIXME In some configurations, the file is transmitted PLAIN */
|
||||||
Dbprintf("CRC not verified in decyphered stream");
|
Dbprintf("CRC not verified in decyphered stream");
|
||||||
|
@ -752,14 +775,14 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
Dbprintf("Unknown communication settings");
|
Dbprintf("Unknown communication settings");
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue