Fix DES authentification and format picc

This commit is contained in:
Bjoern Kerler 2020-06-13 14:19:21 +02:00
commit 5adc8e876a
4 changed files with 967 additions and 548 deletions

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@
#include "desfire_crypto.h" #include "desfire_crypto.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <util.h>
#include "commonutil.h" #include "commonutil.h"
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#include "mbedtls/des.h" #include "mbedtls/des.h"
@ -406,6 +407,8 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
communication_settings|=NO_CRC;
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
if (!(communication_settings & MAC_COMMAND)) if (!(communication_settings & MAC_COMMAND))
@ -508,6 +511,9 @@ 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; void *edata = NULL;
tag->crypto_buffer_size=*nbytes*2;
tag->crypto_buffer=(uint8_t*)malloc(tag->crypto_buffer_size);
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;
@ -527,6 +533,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
communication_settings|=NO_CRC;
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) {
@ -540,18 +547,20 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break; break;
} }
size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings); size_t edl = enciphered_data_length(tag, *nbytes, communication_settings);
edata = malloc(edl); edata = malloc(edl);
memcpy(edata, data, *nbytes - 1); memcpy(edata, data, *nbytes);
memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); memset((uint8_t *)edata + *nbytes , 0, edl - *nbytes);
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, (uint8_t *)edata + edl - 8, 4)) {
PrintAndLogEx(NORMAL, "Expected MAC %s", sprint_hex(data+*nbytes, key_macing_length(key)));
PrintAndLogEx(NORMAL, "Actual MAC %s", sprint_hex(edata + edl - 8, key_macing_length(key)));
#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, key_macing_length(key), "Expect ", 0);
hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0); hexdump((uint8_t *)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;
@ -644,17 +653,19 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
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); if (res!=NULL) {
memcpy(res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3; crc_pos = (*nbytes) - 16 - 3;
if (crc_pos < 0) { if (crc_pos < 0) {
/* Single block */ /* Single block */
crc_pos = 0; crc_pos = 0;
}
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;
} }
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; break;
} }
@ -725,6 +736,9 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break; break;
} }
free(tag->crypto_buffer);
tag->crypto_buffer_size=0;
tag->crypto_buffer=NULL;
return res; return res;
} }
@ -854,3 +868,45 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i
offset += block_size; offset += block_size;
} }
} }
#define CRC32_PRESET 0xFFFFFFFF
static void
desfire_crc32_byte(uint32_t *crc, const uint8_t value)
{
/* x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 */
const uint32_t poly = 0xEDB88320;
*crc ^= value;
for (int current_bit = 7; current_bit >= 0; current_bit--) {
int bit_out = (*crc) & 0x00000001;
*crc >>= 1;
if (bit_out)
*crc ^= poly;
}
}
void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc)
{
uint32_t desfire_crc = CRC32_PRESET;
for (size_t i = 0; i < len; i++) {
desfire_crc32_byte(&desfire_crc, data[i]);
}
*((uint32_t *)(crc)) = htole32(desfire_crc);
}
void desfire_crc32_append(uint8_t *data, const size_t len)
{
desfire_crc32(data, len, data + len);
}
void iso14443a_crc_append(uint8_t* data, size_t len)
{
return compute_crc(CRC_14443_A, data, len, data+len, data+len+1);
}
void iso14443a_crc(uint8_t* data, size_t len, uint8_t* pbtCrc)
{
return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc+1);
}

View file

@ -129,4 +129,8 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
void cmac_generate_subkeys(desfirekey_t key); void cmac_generate_subkeys(desfirekey_t key);
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
#endif void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc);
void desfire_crc32_append(uint8_t *data, const size_t len);
void iso14443a_crc_append(uint8_t* data, size_t len);
void iso14443a_crc(uint8_t* data, size_t len, uint8_t* pbtCrc);
#endif

View file

@ -359,6 +359,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MFDES_READSIG 0x3C #define MFDES_READSIG 0x3C
#define MFDES_WRITE_DATA 0x3D #define MFDES_WRITE_DATA 0x3D
#define MFDES_GET_KEY_SETTINGS 0x45 #define MFDES_GET_KEY_SETTINGS 0x45
#define MFDES_GET_UID 0x51
#define MFDES_CHANGE_KEY_SETTINGS 0x54 #define MFDES_CHANGE_KEY_SETTINGS 0x54
#define MFDES_SELECT_APPLICATION 0x5A #define MFDES_SELECT_APPLICATION 0x5A
#define MFDES_CHANGE_FILE_SETTINGS 0x5F #define MFDES_CHANGE_FILE_SETTINGS 0x5F