Merge CRC location / verification in mifare_cryto_postprocess_data().
Fix issue 52.
This commit is contained in:
parent
de64cce14c
commit
35b87d4acd
1 changed files with 77 additions and 72 deletions
|
@ -524,9 +524,32 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
||||||
case MDCM_ENCIPHERED:
|
case MDCM_ENCIPHERED:
|
||||||
(*nbytes)--;
|
(*nbytes)--;
|
||||||
bool verified = false;
|
bool verified = false;
|
||||||
|
int crc_pos;
|
||||||
int end_crc_pos;
|
int end_crc_pos;
|
||||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
uint8_t x;
|
||||||
case AS_LEGACY:
|
|
||||||
|
/*
|
||||||
|
* AS_LEGACY:
|
||||||
|
* ,-----------------+-------------------------------+--------+
|
||||||
|
* \ BLOCK n-1 | BLOCK n | STATUS |
|
||||||
|
* / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
|
||||||
|
* `-----------------+-------------------------------+--------+
|
||||||
|
*
|
||||||
|
* <------------ DATA ------------>
|
||||||
|
* FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
|
||||||
|
*
|
||||||
|
* AS_NEW:
|
||||||
|
* ,-------------------------------+-----------------------------------------------+--------+
|
||||||
|
* \ BLOCK n-1 | BLOCK n | STATUS |
|
||||||
|
* / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
|
||||||
|
* `-------------------------------+-----------------------------------------------+--------+
|
||||||
|
* <----------------------------------- DATA ------------------------------------->|
|
||||||
|
*
|
||||||
|
* <----------------- DATA ---------------->
|
||||||
|
* FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
|
||||||
|
* `------------------'
|
||||||
|
*/
|
||||||
|
|
||||||
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
|
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -534,72 +557,41 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
||||||
* can't start by the end because the CRC is supposed to be 0 when
|
* can't start by the end because the CRC is supposed to be 0 when
|
||||||
* verified, and accumulating 0's in it should not change it.
|
* verified, and accumulating 0's in it should not change it.
|
||||||
*/
|
*/
|
||||||
end_crc_pos = *nbytes - 7; // The CRC can be over two blocks
|
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||||
|
case AS_LEGACY:
|
||||||
do {
|
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
|
||||||
uint16_t crc;
|
break;
|
||||||
iso14443a_crc (res, end_crc_pos, (uint8_t *)&crc);
|
case AS_NEW:
|
||||||
if (!crc) {
|
/* Move status between payload and CRC */
|
||||||
verified = true;
|
res = assert_crypto_buffer_size (tag, (*nbytes) + 1);
|
||||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
memcpy (res, data, *nbytes);
|
||||||
uint8_t byte = ((uint8_t *)res)[n];
|
|
||||||
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
|
crc_pos = (*nbytes) - 16 - 3;
|
||||||
verified = false;
|
if (crc_pos < 0) {
|
||||||
}
|
/* Single block */
|
||||||
}
|
crc_pos = 0;
|
||||||
if (verified) {
|
}
|
||||||
*nbytes = end_crc_pos - 2;
|
memmove (res + crc_pos + 1, res + crc_pos, *nbytes - crc_pos);
|
||||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
((uint8_t *)res)[crc_pos] = 0x00;
|
||||||
} else {
|
crc_pos++;
|
||||||
end_crc_pos++;
|
*nbytes += 1;
|
||||||
}
|
break;
|
||||||
} while (!verified && (end_crc_pos < *nbytes));
|
}
|
||||||
|
|
||||||
if (!verified) {
|
|
||||||
#if WITH_DEBUG
|
|
||||||
warnx ("(3)DES not verified");
|
|
||||||
#endif
|
|
||||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
|
||||||
*nbytes = -1;
|
|
||||||
res = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AS_NEW:
|
|
||||||
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ,----------------------------+-----------------------------------------+-------------+
|
|
||||||
* \ BLOCK n-1 | BLOCK n | STATUS|
|
|
||||||
* / DATA | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x00 | 0x00 | ... | 0x00 | 0x91 | 0x00 |
|
|
||||||
* `----------------------------+-----------------------------------------+-------------+
|
|
||||||
* <------------------------------ DATA --------------------------------->|
|
|
||||||
*
|
|
||||||
* <----------------- DATA ---------------->
|
|
||||||
* FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
|
|
||||||
* ^ |
|
|
||||||
* | |
|
|
||||||
* `------------------'
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Move status between payload and CRC */
|
|
||||||
res = assert_crypto_buffer_size (tag, (*nbytes) + 1);
|
|
||||||
memcpy (res, data, *nbytes);
|
|
||||||
|
|
||||||
int crc_pos = (*nbytes) - 16 - 3;
|
|
||||||
if (crc_pos < 0) {
|
|
||||||
/* Single block */
|
|
||||||
crc_pos = 0;
|
|
||||||
}
|
|
||||||
memmove (res + crc_pos + 1, res + crc_pos, *nbytes - crc_pos);
|
|
||||||
((uint8_t *)res)[crc_pos] = 0x00;
|
|
||||||
crc_pos++;
|
|
||||||
*nbytes += 1;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
uint16_t crc16;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
end_crc_pos = crc_pos + 4;
|
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||||
desfire_crc32 (res, end_crc_pos, (uint8_t *)&crc);
|
case AS_LEGACY:
|
||||||
|
end_crc_pos = crc_pos + 2;
|
||||||
|
iso14443a_crc (res, end_crc_pos, (uint8_t *)&crc16);
|
||||||
|
crc = crc16;
|
||||||
|
break;
|
||||||
|
case AS_NEW:
|
||||||
|
end_crc_pos = crc_pos + 4;
|
||||||
|
desfire_crc32 (res, end_crc_pos, (uint8_t *)&crc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!crc) {
|
if (!crc) {
|
||||||
verified = true;
|
verified = true;
|
||||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||||
|
@ -609,26 +601,39 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verified) {
|
if (verified) {
|
||||||
*nbytes = crc_pos - 1;
|
*nbytes = crc_pos;
|
||||||
|
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||||
|
case AS_LEGACY:
|
||||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
||||||
|
break;
|
||||||
|
case AS_NEW:
|
||||||
|
/* The status byte was already before the CRC */
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t x = ((uint8_t *)res)[crc_pos - 1];
|
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||||
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
|
case AS_LEGACY:
|
||||||
((uint8_t *)res)[crc_pos] = x;
|
break;
|
||||||
|
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++;
|
crc_pos++;
|
||||||
}
|
}
|
||||||
} while (!verified && (end_crc_pos < *nbytes));
|
} while (!verified && (end_crc_pos < *nbytes));
|
||||||
|
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
#if WITH_DEBUG
|
#if WITH_DEBUG
|
||||||
hexdump (res, *nbytes, "KO ", 0);
|
/* FIXME In some configurations, the file is transmitted PLAIN */
|
||||||
warnx ("AES not verified");
|
warnx ("CRC not verified in decyphered stream");
|
||||||
#endif
|
#endif
|
||||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warnx ("Unknown communication settings");
|
warnx ("Unknown communication settings");
|
||||||
|
|
Loading…
Add table
Reference in a new issue