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:
iceman1001 2024-05-15 09:36:31 +02:00
commit 498af46fbf

View file

@ -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;
} }