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:
|
||||
(*nbytes)--;
|
||||
bool verified = false;
|
||||
int crc_pos;
|
||||
int end_crc_pos;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
uint8_t x;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
* verified, and accumulating 0's in it should not change it.
|
||||
*/
|
||||
end_crc_pos = *nbytes - 7; // The CRC can be over two blocks
|
||||
|
||||
do {
|
||||
uint16_t crc;
|
||||
iso14443a_crc (res, end_crc_pos, (uint8_t *)&crc);
|
||||
if (!crc) {
|
||||
verified = true;
|
||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||
uint8_t byte = ((uint8_t *)res)[n];
|
||||
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
|
||||
verified = false;
|
||||
}
|
||||
}
|
||||
if (verified) {
|
||||
*nbytes = end_crc_pos - 2;
|
||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
||||
} else {
|
||||
end_crc_pos++;
|
||||
}
|
||||
} 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;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
|
||||
break;
|
||||
case AS_NEW:
|
||||
/* Move status between payload and CRC */
|
||||
res = assert_crypto_buffer_size (tag, (*nbytes) + 1);
|
||||
memcpy (res, data, *nbytes);
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
uint16_t crc16;
|
||||
uint32_t crc;
|
||||
end_crc_pos = crc_pos + 4;
|
||||
desfire_crc32 (res, end_crc_pos, (uint8_t *)&crc);
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
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) {
|
||||
verified = true;
|
||||
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) {
|
||||
*nbytes = crc_pos - 1;
|
||||
*nbytes = crc_pos;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
||||
break;
|
||||
case AS_NEW:
|
||||
/* The status byte was already before the CRC */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint8_t x = ((uint8_t *)res)[crc_pos - 1];
|
||||
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
|
||||
((uint8_t *)res)[crc_pos] = x;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
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++;
|
||||
}
|
||||
} while (!verified && (end_crc_pos < *nbytes));
|
||||
|
||||
if (!verified) {
|
||||
#if WITH_DEBUG
|
||||
hexdump (res, *nbytes, "KO ", 0);
|
||||
warnx ("AES not verified");
|
||||
/* FIXME In some configurations, the file is transmitted PLAIN */
|
||||
warnx ("CRC not verified in decyphered stream");
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
warnx ("Unknown communication settings");
|
||||
|
|
Loading…
Reference in a new issue