Do not abort on crypto error.
Because in some circumstances the crypto is skipped regardless of the communication settings by the Mifare DESFire (e.g. when reading a file which is writable with any key), do not abort if the crypto fail, and make it possible to the user to catch such an event to fix his code accordingly. Only display crypto diagnostic if compiled with debug support.
This commit is contained in:
parent
04fe89e78c
commit
22e9854995
8 changed files with 103 additions and 14 deletions
1
NEWS
1
NEWS
|
@ -2,6 +2,7 @@ Changes between 0.3.0 and 0.3.1 [XX xxx XXXX]
|
|||
|
||||
*) Fix mifare_classic_transfer() for devices returning a 1 byte response on
|
||||
success.
|
||||
*) New API function mifare_desfire_last_pcd_error().
|
||||
|
||||
Changes between 0.2.3 and 0.3.0 [23 dec 2010]
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ linkedman = \
|
|||
freefare_error.3 freefare_perror.3 \
|
||||
freefare_error.3 freefare_strerror.3 \
|
||||
freefare_error.3 freefare_strerror_r.3 \
|
||||
freefare_error.3 mifare_desfire_last_pcd_error.3 \
|
||||
freefare_error.3 mifare_desfire_last_picc_error.3 \
|
||||
mad.3 mad_free.3 \
|
||||
mad.3 mad_get_aid.3 \
|
||||
|
|
|
@ -244,6 +244,10 @@ enum mifare_desfire_file_types {
|
|||
#define FILE_NOT_FOUND 0xF0
|
||||
#define FILE_INTEGRITY_ERROR 0xF1
|
||||
|
||||
/* Error code managed by the library */
|
||||
|
||||
#define CRYPTO_ERROR 0x01
|
||||
|
||||
struct mifare_desfire_aid;
|
||||
typedef struct mifare_desfire_aid *MifareDESFireAID;
|
||||
|
||||
|
@ -251,6 +255,7 @@ MifareDESFireAID mifare_desfire_aid_new (uint32_t aid);
|
|||
MifareDESFireAID mifare_desfire_aid_new_with_mad_aid (MadAid mad_aid, uint8_t n);
|
||||
uint32_t mifare_desfire_aid_get_aid (MifareDESFireAID aid);
|
||||
|
||||
uint8_t mifare_desfire_last_pcd_error (MifareTag tag);
|
||||
uint8_t mifare_desfire_last_picc_error (MifareTag tag);
|
||||
|
||||
#pragma pack (push)
|
||||
|
|
|
@ -53,6 +53,8 @@ Mifare card manipulation library (libfreefare, \-lfreefare)
|
|||
.Ft "void"
|
||||
.Fn freefare_strerror "MifareTag tag" "char *string"
|
||||
.Ft uint8_t
|
||||
.Fm mifare_desfire_last_pcd_error "MifareTag tag"
|
||||
.Ft uint8_t
|
||||
.Fm mifare_desfire_last_picc_error "MifareTag tag"
|
||||
.\" ____ _ _ _
|
||||
.\" | _ \ ___ ___ ___ _ __(_)_ __ | |_(_) ___ _ __
|
||||
|
@ -84,6 +86,10 @@ function displays the last PCD or PICC error encounred using
|
|||
to stderr.
|
||||
.Pp
|
||||
The
|
||||
.Fn mifare_desfire_last_pcd_error
|
||||
function returns the error code of the last function call from the library.
|
||||
.Pp
|
||||
The
|
||||
.Fn mifare_desfire_last_picc_error
|
||||
function returns the error code returned by the last command run on
|
||||
.Vt tag .
|
||||
|
@ -97,9 +103,11 @@ function returns the error code returned by the last command run on
|
|||
.Fn freefare_strerror
|
||||
returns the error message,
|
||||
.Fn freefare_strerror_r
|
||||
returns 0 on success, -1 on failure, and
|
||||
returns 0 on success, -1 on failure;
|
||||
.Fn mifare_desfire_last_pcd_error
|
||||
and
|
||||
.Fn mifare_desfire_last_picc_error
|
||||
returns an error code or 0 if no error is known or
|
||||
return an error code or 0 if no error occured or if
|
||||
.Vt tag
|
||||
is not a Mifare DESFire target.
|
||||
.\" ____ _
|
||||
|
|
|
@ -169,6 +169,7 @@ static ssize_t read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_
|
|||
/* reply length */ \
|
||||
__msg[__len-1] = 0x00; \
|
||||
MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK; \
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK; \
|
||||
DEBUG_XFER (__msg, __len, "===> "); \
|
||||
if (!(nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, &__##res##_n))) { \
|
||||
return errno = EIO, -1; \
|
||||
|
@ -326,8 +327,6 @@ authenticate (MifareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key)
|
|||
|
||||
memset (MIFARE_DESFIRE (tag)->ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
|
||||
|
||||
MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
|
||||
|
||||
MIFARE_DESFIRE (tag)->authenticated_key_no = NOT_YET_AUTHENTICATED;
|
||||
free (MIFARE_DESFIRE (tag)->session_key);
|
||||
MIFARE_DESFIRE (tag)->session_key = NULL;
|
||||
|
@ -1305,7 +1304,7 @@ read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t
|
|||
break;
|
||||
}
|
||||
}
|
||||
uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 8, cs | CMAC_COMMAND);
|
||||
uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 8, MDCM_PLAIN | CMAC_COMMAND);
|
||||
cs = ocs;
|
||||
|
||||
/*
|
||||
|
@ -1329,7 +1328,7 @@ read_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t
|
|||
ssize_t sr = bytes_received;
|
||||
p = mifare_cryto_postprocess_data (tag, data, &sr, cs | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY);
|
||||
|
||||
return sr - 1;
|
||||
return (sr <= 0) ? sr : sr - 1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
|
@ -1387,7 +1386,7 @@ write_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_
|
|||
}
|
||||
|
||||
ssize_t sn = __res_n;
|
||||
p = mifare_cryto_postprocess_data (tag, res, &sn, MDCM_MACED | CMAC_COMMAND | CMAC_VERIFY);
|
||||
p = mifare_cryto_postprocess_data (tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
|
||||
|
||||
if (0x00 == p[__res_n-1]) {
|
||||
// Remove header length
|
||||
|
|
|
@ -473,12 +473,12 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
|||
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)) {
|
||||
warnx ("MACing not verified");
|
||||
#if WITH_DEBUG
|
||||
warnx ("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);
|
||||
abort ();
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
|
@ -507,8 +507,8 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
|||
warnx ("CMAC NOT verified :-(");
|
||||
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
|
||||
hexdump (MIFARE_DESFIRE (tag)->cmac, 8, "Actual ", 0);
|
||||
abort ();
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
} else {
|
||||
|
@ -555,10 +555,10 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
|||
} while (!verified && (end_crc_pos < *nbytes));
|
||||
|
||||
if (!verified) {
|
||||
warnx ("(3)DES not verified");
|
||||
#if WITH_DEBUG
|
||||
abort ();
|
||||
warnx ("(3)DES not verified");
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
|
@ -582,12 +582,12 @@ mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int c
|
|||
desfire_crc32 (res, p - (uint8_t *)res, crc);
|
||||
|
||||
if (memcmp (crc, crc_ref, 4)) {
|
||||
warnx ("AES CRC32 not verified in AES stream");
|
||||
#if WITH_DEBUG
|
||||
warnx ("AES CRC32 not verified in AES stream");
|
||||
hexdump (crc_ref, 4, "Expect ", 0);
|
||||
hexdump (crc, 4, "Actual ", 0);
|
||||
abort ();
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ static struct error_message {
|
|||
EM(EEPROM_ERROR),
|
||||
EM(FILE_NOT_FOUND),
|
||||
EM(FILE_INTEGRITY_ERROR),
|
||||
EM(CRYPTO_ERROR),
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -70,6 +71,15 @@ mifare_desfire_error_lookup (uint8_t code)
|
|||
return "Invalid error code";
|
||||
}
|
||||
|
||||
uint8_t
|
||||
mifare_desfire_last_pcd_error (MifareTag tag)
|
||||
{
|
||||
if (tag->tag_info->type != DESFIRE)
|
||||
return 0;
|
||||
|
||||
return MIFARE_DESFIRE (tag)->last_pcd_error;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
mifare_desfire_last_picc_error (MifareTag tag)
|
||||
{
|
||||
|
|
|
@ -930,3 +930,68 @@ test_mifare_desfire_des_macing (void)
|
|||
|
||||
mifare_desfire_key_free (key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_free_read (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
mifare_desfire_auto_authenticate (tag, 0);
|
||||
|
||||
/* Wipeout the card */
|
||||
res = mifare_desfire_format_picc (tag);
|
||||
cut_assert_success ("mifare_desfire_format_picc()");
|
||||
|
||||
mifare_desfire_auto_authenticate (tag, 0);
|
||||
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version (key_data_null);
|
||||
res = mifare_desfire_change_key (tag, 0, key, NULL);
|
||||
cut_assert_success ("mifare_desfire_change_key()");
|
||||
|
||||
res = mifare_desfire_authenticate (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate()");
|
||||
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new (0x00123456);
|
||||
res = mifare_desfire_create_application (tag, aid, 0xFF, 2);
|
||||
cut_assert_success ("mifare_desfire_create_application()");
|
||||
|
||||
res = mifare_desfire_select_application (tag, aid);
|
||||
cut_assert_success ("mifare_desfire_select_application");
|
||||
free (aid);
|
||||
|
||||
res = mifare_desfire_authenticate (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate()");
|
||||
|
||||
res = mifare_desfire_create_std_data_file (tag, 1, MDCM_MACED, 0x0000, 20);
|
||||
cut_assert_success ("mifare_desfire_create_std_data_file()");
|
||||
|
||||
char *s= "Hello World";
|
||||
res = mifare_desfire_write_data (tag, 1, 0, strlen (s), s);
|
||||
cut_assert_success ("mifare_desfire_write_data()");
|
||||
|
||||
res = mifare_desfire_change_file_settings (tag, 1, MDCM_ENCIPHERED, 0xEFFF);
|
||||
cut_assert_success ("mifare_desfire_change_file_settings");
|
||||
|
||||
char buffer[20];
|
||||
res = mifare_desfire_read_data (tag, 1, 0, 0, buffer);
|
||||
cut_assert_equal_int (sizeof (buffer), res, cut_message ("Data with free access should be read in PLAIN mode only."));
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_pcd_error (tag), cut_message ("Wrong PCD error"));
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 0, 0, buffer, MDCM_MACED);
|
||||
cut_assert_equal_int (-1, res, cut_message ("Data with free access should be read in PLAIN mode only."));
|
||||
cut_assert_equal_int (CRYPTO_ERROR, mifare_desfire_last_pcd_error (tag), cut_message ("Wrong PCD error"));
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 0, 0, buffer, MDCM_ENCIPHERED);
|
||||
cut_assert_equal_int (-1, res, cut_message ("Data with free access should be read in PLAIN mode only."));
|
||||
cut_assert_equal_int (CRYPTO_ERROR, mifare_desfire_last_pcd_error (tag), cut_message ("Wrong PCD error"));
|
||||
|
||||
/* Wipeout the card */
|
||||
mifare_desfire_select_application (tag, NULL);
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_pcd_error (tag), cut_message ("Wrong PCD error"));
|
||||
res = mifare_desfire_authenticate (tag, 0, key);
|
||||
|
||||
res = mifare_desfire_format_picc (tag);
|
||||
cut_assert_success ("mifare_desfire_format_picc()");
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue