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 *res = data;
void *edata = NULL;
uint8_t first_cmac_byte = 0x00;
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key)
if (!key) {
return data;
}
// Return directly if we just have a status code.
if (1 == *nbytes)
if (1 == *nbytes) {
return res;
}
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;
}
}
/* pass through */
case MDCM_MACED:
case MDCM_MACED: {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
if (communication_settings & MAC_VERIFY) {
case AS_LEGACY: {
if ((communication_settings & MAC_VERIFY) == MAC_VERIFY) {
*nbytes -= key_macing_length(key);
if (*nbytes == 0) {
*nbytes = -1;
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);
edata = BigBuf_malloc(edl);
uint8_t edata[edl];
memset(edata, 0, sizeof(edata));
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);
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
Dbprintf("MACing not verified");
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
DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
@ -596,10 +600,16 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
}
}
break;
case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
}
case AS_NEW: {
if ((communication_settings & CMAC_COMMAND) != CMAC_COMMAND) {
break;
if (communication_settings & CMAC_VERIFY) {
}
int n = 0;
if ((communication_settings & CMAC_VERIFY) == CMAC_VERIFY) {
if (*nbytes < 9) {
*nbytes = -1;
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];
((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);
if (communication_settings & CMAC_VERIFY) {
if ((communication_settings & CMAC_VERIFY) == CMAC_VERIFY) {
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
#ifdef WITH_DEBUG
Dbprintf("CMAC NOT verified :-(");
@ -628,12 +641,11 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
}
}
break;
}
}
free(edata);
break;
case MDCM_ENCIPHERED:
}
case MDCM_ENCIPHERED: {
(*nbytes)--;
bool verified = false;
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.
*/
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
crc_pos = 0; // Single block
}
break;
case AS_NEW:
}
case AS_NEW: {
/* Move status between payload and CRC */
res = DESFIRE(tag)->crypto_buffer;
memcpy(res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3;
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
crc_pos = 0; // Single block
}
memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++;
*nbytes += 1;
break;
}
}
do {
uint16_t crc_16 = 0x00;
uint32_t crc = 0x00;
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
AddCrc14A((uint8_t *)res, end_crc_pos);
end_crc_pos = crc_pos + 2;
//
crc = crc_16;
break;
case AS_NEW:
}
case AS_NEW: {
end_crc_pos = crc_pos + 4;
crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
break;
}
}
if (!crc) {
if (crc == 0) {
verified = true;
for (int n = end_crc_pos; n < *nbytes - 1; 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;
}
}
if (verified) {
*nbytes = crc_pos;
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
((uint8_t *)data)[(*nbytes)++] = 0x00;
break;
case AS_NEW:
}
case AS_NEW: {
/* The status byte was already before the CRC */
break;
}
}
} else {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
break;
case AS_NEW:
}
case AS_NEW: {
x = ((uint8_t *)res)[crc_pos - 1];
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
((uint8_t *)res)[crc_pos] = x;
break;
}
}
crc_pos++;
}
} while (!verified && (end_crc_pos < *nbytes));
if (!verified) {
} while (verified == false && (end_crc_pos < *nbytes));
if (verified == false) {
#ifdef WITH_DEBUG
/* FIXME In some configurations, the file is transmitted PLAIN */
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;
res = NULL;
}
break;
default:
}
default: {
Dbprintf("Unknown communication settings");
*nbytes = -1;
res = NULL;
break;
}
}
return res;
}