Cleanup: Replace DESFIRE_TRANSCEIVE by a function (#105)

The work for this commit was outlined by the third item from the TODO:

> ### The `DESFIRE_TRANSCEIVE` macro should be replaced by a function ###
>
> `DESFIRE_TRANSCEIVE` was originaly a macro to enclose a
> `nfc_initiator_transceive_bytes()` call with debug lines.  The
> functions has unexpectedly grown up and is now between 25 and 100
> lines of code (depending of my refactoring mood).  The main
> drawbacks are poor readability, redundant code in the binary,
> debuggers don't cope well with macros, and by design it sucks.

Thanks @broth-itk for submitting this change.
This commit is contained in:
broth-itk 2019-11-05 20:42:53 +01:00 committed by Robert Quattlebaum
parent 7f695cfbec
commit 682fbe69bd
3 changed files with 249 additions and 107 deletions

6
TODO
View file

@ -3,12 +3,6 @@
mifare_classic_authenticate() with a NULL key). mifare_classic_authenticate() with a NULL key).
[ ] MAD and MifareApplication functions are tied to mifare_clasic_* ones and [ ] MAD and MifareApplication functions are tied to mifare_clasic_* ones and
some refactoring is required to have a consistent API. some refactoring is required to have a consistent API.
[ ] The DESFIRE_TRANSCEIVE macro should be replaced by a function
DESFIRE_TRANSCEIVE was originaly a macro to enclose a nfc_initiator_trans-
ceive_bytes() call with debug lines. The functions has unexpectedly grown
up and is now between 25 and 100 lines of code (depending of my refactoring
mood). The main drawbacks are poor readability, redundant code in the
binary, debuggers don't cope well with macros, and by design it sucks.
[ ] Refactor examples and have consistent behavior. [ ] Refactor examples and have consistent behavior.
Dump to stdout unless -o is specified; Dump to stdout unless -o is specified;
Read from stdin unless a file is specified; Read from stdin unless a file is specified;

View file

@ -83,6 +83,7 @@ struct mifare_desfire_raw_file_settings {
static struct mifare_desfire_file_settings cached_file_settings[MAX_FILE_COUNT]; static struct mifare_desfire_file_settings cached_file_settings[MAX_FILE_COUNT];
static bool cached_file_settings_current[MAX_FILE_COUNT]; static bool cached_file_settings_current[MAX_FILE_COUNT];
static int desfire_transceive(FreefareTag tag, const uint8_t *msg, size_t msg_len, uint8_t *res, size_t res_size, size_t *res_len);
static int authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key); static int authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key);
static int create_file1(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size); static int create_file1(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
static int create_file2(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records); static int create_file2(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
@ -120,12 +121,15 @@ static ssize_t read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off
} \ } \
} while (0) } while (0)
/*
* Convenience macros.
*/
/* Max APDU sizes to be ISO encapsulated by DESFIRE_TRANSCEIVE()
/* Native DESFire APDUs will be wrapped in ISO7816-4 APDUs:
CAPDUs will be 5 bytes longer (CLA+P1+P2+Lc+Le)
RAPDUs will be 1 byte longer (SW1 SW2 instead of 1 status byte)
Max APDU sizes to be ISO encapsulated by desfire_transceive()
From MIFARE DESFire Functional specification: From MIFARE DESFire Functional specification:
MAX_CAPDU_SIZE: "The length of the total wrapped DESFire MAX_CAPDU_SIZE: "The length of the total wrapped DESFire
command is not longer than 55 byte long." command is not longer than 55 byte long."
@ -141,49 +145,89 @@ static ssize_t read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off
* The Mifare DESFire function return value which is returned at the end of the * The Mifare DESFire function return value which is returned at the end of the
* response is copied at the beginning to match the PICC documentation. * response is copied at the beginning to match the PICC documentation.
*/ */
#define DESFIRE_TRANSCEIVE(tag, msg, res) \ static int
DESFIRE_TRANSCEIVE2 (tag, msg, __##msg##_n, res) desfire_transceive(FreefareTag tag, const uint8_t *msg, size_t msg_len, uint8_t *res, size_t res_size, size_t *res_len)
/* Native DESFire APDUs will be wrapped in ISO7816-4 APDUs: {
CAPDUs will be 5 bytes longer (CLA+P1+P2+Lc+Le) uint8_t msg_buf[MAX_CAPDU_SIZE + 5];
RAPDUs will be 1 byte longer (SW1 SW2 instead of 1 status byte) uint8_t res_buf[MAX_RAPDU_SIZE + 1];
*/
#define DESFIRE_TRANSCEIVE2(tag, msg, msg_len, res) \ size_t len = 5;
do { \ int rc;
DEBUG_FUNCTION(); \
static uint8_t __msg[MAX_CAPDU_SIZE + 5] = { 0x90, 0x00, 0x00, 0x00, 0x00, /* ..., */ 0x00 }; \ if (!msg) {
/* CLA INS P1 P2 Lc PAYLOAD LE*/ \ errno = EINVAL;
static uint8_t __res[MAX_RAPDU_SIZE + 1]; \ return -1;
size_t __len = 5; \ }
errno = 0; \
if (!msg) return errno = EINVAL, -1; \ memset (msg_buf, 0, sizeof(msg_buf));
__msg[1] = msg[0]; \ msg_buf[0] = 0x90; // CLA
if (msg_len > 1) { \ msg_buf[1] = msg[0]; // INS
__len += msg_len; \ // P1 & P2 is zero by default
__msg[4] = msg_len - 1; \
memcpy (__msg + 5, msg + 1, msg_len - 1); \ if (msg_len > 1) {
} \ len += msg_len;
/* reply length */ \ msg_buf[4] = msg_len - 1; // Lc
__msg[__len-1] = 0x00; \ memcpy (msg_buf + 5, msg + 1, msg_len - 1);
MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK; \ }
MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK; \
DEBUG_XFER (__msg, __len, "===> "); \ MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
int _res; \ MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK;
if ((_res = nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, __##res##_size + 1, tag->timeout)) < 0) { \
return errno = (errno == ETIMEDOUT) ? errno : EIO, -1; \ DEBUG_XFER (msg_buf, len, "===> ");
} \
__##res##_n = _res; \ if ((rc = nfc_initiator_transceive_bytes (tag->device, msg_buf, len, res_buf, sizeof(res_buf), tag->timeout)) < 2) {
DEBUG_XFER (__res, __##res##_n, "<=== "); \ errno = (errno == ETIMEDOUT) ? errno : EIO;
res[__##res##_n-2] = __res[__##res##_n-1]; \ return -1;
__##res##_n--; \ }
if ((1 == __##res##_n) && (ADDITIONAL_FRAME != res[__##res##_n-1]) && (OPERATION_OK != res[__##res##_n-1])) { \
if (res[0] == AUTHENTICATION_ERROR) \ DEBUG_XFER (res_buf, rc, "<=== ");
errno = EACCES; \
return MIFARE_DESFIRE (tag)->last_picc_error = res[0], -1; \ rc--;
} \ if (rc > (int)res_size) {
memcpy (res, __res, __##res##_n - 1); \ errno = ENOBUFS;
} while (0) return -1;
}
int lpe = res_buf[rc];
res[rc - 1] = lpe;
if ((1 == rc) && (ADDITIONAL_FRAME != res_buf[rc]) && (OPERATION_OK != res_buf[rc])) {
if (AUTHENTICATION_ERROR == lpe)
errno = EACCES;
MIFARE_DESFIRE (tag)->last_picc_error = lpe;
return -1;
}
if (res_len)
*res_len = rc;
memcpy (res, res_buf, rc - 1);
errno = 0;
return 0;
}
/*
* Convenience macros.
*/
#ifdef WITH_DEBUG
// define a small but cute wrapper to allow debug output
#define MIFARE_DESFIRE_TRANSCEIVE(tag, msg, msg_len, res, res_size, res_len) ({ \
int __err = 0; \
do { \
DEBUG_FUNCTION(); \
__err = desfire_transceive(tag, msg, msg_len, res, res_size, res_len); \
} while (0); \
__err; \
})
#else
#define MIFARE_DESFIRE_TRANSCEIVE desfire_transceive
#endif
/* /*
* Miscellaneous low-level memory manipulation functions. * Miscellaneous low-level memory manipulation functions.
*/ */
@ -234,7 +278,6 @@ mifare_desfire_taste(nfc_device *device, nfc_target target)
memcmp(target.nti.nai.abtAts, "\x75\x77\x81\x02", 4) == 0; memcmp(target.nti.nai.abtAts, "\x75\x77\x81\x02", 4) == 0;
} }
/* /*
* Memory management functions. * Memory management functions.
*/ */
@ -272,7 +315,6 @@ mifare_desfire_tag_free(FreefareTag tag)
free(tag); free(tag);
} }
/* /*
* MIFARE card communication preparation functions * MIFARE card communication preparation functions
* *
@ -341,7 +383,6 @@ mifare_desfire_disconnect(FreefareTag tag)
return 0; return 0;
} }
#define AUTHENTICATE_LEGACY 0x0A #define AUTHENTICATE_LEGACY 0x0A
#define AUTHENTICATE_ISO 0x1A #define AUTHENTICATE_ISO 0x1A
@ -350,6 +391,8 @@ mifare_desfire_disconnect(FreefareTag tag)
static int static int
authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key) authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
memset(MIFARE_DESFIRE(tag)->ivect, 0, MAX_CRYPTO_BLOCK_SIZE); memset(MIFARE_DESFIRE(tag)->ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
@ -366,7 +409,8 @@ authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key)
BUFFER_APPEND(cmd1, cmd); BUFFER_APPEND(cmd1, cmd);
BUFFER_APPEND(cmd1, key_no); BUFFER_APPEND(cmd1, key_no);
DESFIRE_TRANSCEIVE(tag, cmd1, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, cmd1, __cmd1_n, res, __res_size, &__res_n)) < 0)
return rc;
size_t key_length = __res_n - 1; size_t key_length = __res_n - 1;
@ -395,7 +439,8 @@ authenticate(FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key)
BUFFER_APPEND(cmd2, 0xAF); BUFFER_APPEND(cmd2, 0xAF);
BUFFER_APPEND_BYTES(cmd2, token, 2 * key_length); BUFFER_APPEND_BYTES(cmd2, token, 2 * key_length);
DESFIRE_TRANSCEIVE(tag, cmd2, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, cmd2, __cmd2_n, res, __res_size, &__res_n)) < 0)
return rc;
uint8_t PICC_E_RndA_s[16]; uint8_t PICC_E_RndA_s[16];
memcpy(PICC_E_RndA_s, res, key_length); memcpy(PICC_E_RndA_s, res, key_length);
@ -467,6 +512,8 @@ mifare_desfire_authenticate_aes(FreefareTag tag, uint8_t key_no, MifareDESFireKe
int int
mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings) mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_AUTHENTICATED(tag); ASSERT_AUTHENTICATED(tag);
@ -476,9 +523,10 @@ mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings)
BUFFER_APPEND(cmd, 0x54); BUFFER_APPEND(cmd, 0x54);
BUFFER_APPEND(cmd, settings); BUFFER_APPEND(cmd, settings);
char *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_ENCIPHERED | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_ENCIPHERED | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t n = __res_n; ssize_t n = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &n, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_COMMAND | MAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &n, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_COMMAND | MAC_VERIFY);
@ -492,6 +540,8 @@ mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings)
int int
mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max_keys) mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max_keys)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1); BUFFER_INIT(cmd, 1);
@ -499,9 +549,10 @@ mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max
BUFFER_APPEND(cmd, 0x45); BUFFER_APPEND(cmd, 0x45);
char *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, cmd, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t n = __res_n; ssize_t n = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &n, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &n, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -520,6 +571,8 @@ mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max
int int
mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key) mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_AUTHENTICATED(tag); ASSERT_AUTHENTICATED(tag);
@ -607,7 +660,8 @@ mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND | NO_CRC); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND | NO_CRC);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -633,6 +687,8 @@ mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_
int int
mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version) mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_NOT_NULL(version); ASSERT_NOT_NULL(version);
@ -645,7 +701,8 @@ mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY);
@ -658,11 +715,12 @@ mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version
return 0; return 0;
} }
static int static int
create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings1, uint8_t settings2, int want_iso_application, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len) create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings1, uint8_t settings2, int want_iso_application, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 22); BUFFER_INIT(cmd, 22);
@ -684,7 +742,8 @@ create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings1, uin
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY);
@ -734,6 +793,8 @@ mifare_desfire_create_application_aes_iso(FreefareTag tag, MifareDESFireAID aid,
int int
mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid) mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 4 + CMAC_LENGTH); BUFFER_INIT(cmd, 4 + CMAC_LENGTH);
@ -744,7 +805,8 @@ mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -768,6 +830,8 @@ mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid)
int int
mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], size_t *count) mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], size_t *count)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1); BUFFER_INIT(cmd, 1);
@ -780,7 +844,8 @@ mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], si
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
// FIXME This code needs refactoring! // FIXME This code needs refactoring!
memcpy(buffer, res, __res_n); memcpy(buffer, res, __res_n);
@ -788,7 +853,8 @@ mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], si
if (res[__res_n - 1] == 0xAF) { if (res[__res_n - 1] == 0xAF) {
off_t offset = __res_n - 1; off_t offset = __res_n - 1;
p[0] = 0xAF; p[0] = 0xAF;
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
memcpy((uint8_t *)buffer + offset, res, __res_n); memcpy((uint8_t *)buffer + offset, res, __res_n);
__res_n += offset; __res_n += offset;
@ -822,6 +888,8 @@ mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], si
int int
mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *count) mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *count)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
*count = 0; *count = 0;
@ -835,7 +903,8 @@ mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *cou
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
do { do {
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
if (__res_n > 1) { if (__res_n > 1) {
MifareDESFireDF *new_dfs; MifareDESFireDF *new_dfs;
@ -870,6 +939,8 @@ mifare_desfire_free_application_ids(MifareDESFireAID aids[])
int int
mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid) mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
struct mifare_desfire_aid null_aid = { .data = { 0x00, 0x00, 0x00 } }; struct mifare_desfire_aid null_aid = { .data = { 0x00, 0x00, 0x00 } };
@ -886,7 +957,8 @@ mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND);
@ -908,6 +980,8 @@ mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid)
int int
mifare_desfire_format_picc(FreefareTag tag) mifare_desfire_format_picc(FreefareTag tag)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_AUTHENTICATED(tag); ASSERT_AUTHENTICATED(tag);
@ -918,7 +992,8 @@ mifare_desfire_format_picc(FreefareTag tag)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -939,6 +1014,8 @@ mifare_desfire_format_picc(FreefareTag tag)
int int
mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *version_info) mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *version_info)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_NOT_NULL(version_info); ASSERT_NOT_NULL(version_info);
@ -951,16 +1028,19 @@ mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *
BUFFER_APPEND(cmd, 0x60); BUFFER_APPEND(cmd, 0x60);
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
memcpy(&(version_info->hardware), res, 7); memcpy(&(version_info->hardware), res, 7);
memcpy(buffer, res, 7); memcpy(buffer, res, 7);
p[0] = 0xAF; p[0] = 0xAF;
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
memcpy(&(version_info->software), res, 7); memcpy(&(version_info->software), res, 7);
memcpy(buffer + 7, res, 7); memcpy(buffer + 7, res, 7);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
memcpy(&(version_info->uid), res, 14); memcpy(&(version_info->uid), res, 14);
memcpy(buffer + 14, res, __res_n); memcpy(buffer + 14, res, __res_n);
@ -976,6 +1056,8 @@ mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *
int int
mifare_desfire_free_mem(FreefareTag tag, uint32_t *size) mifare_desfire_free_mem(FreefareTag tag, uint32_t *size)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_NOT_NULL(size); ASSERT_NOT_NULL(size);
@ -987,7 +1069,8 @@ mifare_desfire_free_mem(FreefareTag tag, uint32_t *size)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1003,6 +1086,8 @@ mifare_desfire_free_mem(FreefareTag tag, uint32_t *size)
int int
mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enable_random_uid) mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enable_random_uid)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 10); BUFFER_INIT(cmd, 10);
@ -1014,7 +1099,8 @@ mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enab
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1028,6 +1114,8 @@ mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enab
int int
mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key) mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 34); BUFFER_INIT(cmd, 34);
@ -1053,7 +1141,8 @@ mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1067,6 +1156,8 @@ mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key)
int int
mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats) mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 34); BUFFER_INIT(cmd, 34);
@ -1089,7 +1180,8 @@ mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | NO_CRC | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | NO_CRC | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1103,6 +1195,8 @@ mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats)
int int
mifare_desfire_get_card_uid_raw(FreefareTag tag, uint8_t uid[]) mifare_desfire_get_card_uid_raw(FreefareTag tag, uint8_t uid[])
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_NOT_NULL(uid); ASSERT_NOT_NULL(uid);
@ -1114,7 +1208,8 @@ mifare_desfire_get_card_uid_raw(FreefareTag tag, uint8_t uid[])
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 1, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_ENCIPHERED); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_ENCIPHERED);
@ -1147,13 +1242,14 @@ mifare_desfire_get_card_uid(FreefareTag tag, char **uid)
return 0; return 0;
} }
/* Application level commands */ /* Application level commands */
int int
mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count) mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1 + CMAC_LENGTH); BUFFER_INIT(cmd, 1 + CMAC_LENGTH);
@ -1164,7 +1260,8 @@ mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1186,6 +1283,8 @@ mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count)
int int
mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count) mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1); BUFFER_INIT(cmd, 1);
@ -1202,7 +1301,8 @@ mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
do { do {
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
memcpy(data + offset, res, __res_n - 1); memcpy(data + offset, res, __res_n - 1);
offset += __res_n - 1; offset += __res_n - 1;
@ -1237,6 +1337,8 @@ mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count
int int
mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings) mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
if (cached_file_settings_current[file_no]) { if (cached_file_settings_current[file_no]) {
@ -1252,7 +1354,8 @@ mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1295,6 +1398,8 @@ mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare
int int
mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights) mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
struct mifare_desfire_file_settings settings; struct mifare_desfire_file_settings settings;
@ -1314,7 +1419,9 @@ mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t co
BUFFER_APPEND_LE(cmd, access_rights, 2, sizeof(uint16_t)); BUFFER_APPEND_LE(cmd, access_rights, 2, sizeof(uint16_t));
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res);
if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1332,7 +1439,8 @@ mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t co
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1347,6 +1455,8 @@ mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t co
static int static int
create_file1(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size) create_file1(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 10 + CMAC_LENGTH); BUFFER_INIT(cmd, 10 + CMAC_LENGTH);
@ -1360,9 +1470,10 @@ create_file1(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file
BUFFER_APPEND_LE(cmd, access_rights, 2, sizeof(uint16_t)); BUFFER_APPEND_LE(cmd, access_rights, 2, sizeof(uint16_t));
BUFFER_APPEND_LE(cmd, file_size, 3, sizeof(uint32_t)); BUFFER_APPEND_LE(cmd, file_size, 3, sizeof(uint32_t));
char *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1402,6 +1513,8 @@ mifare_desfire_create_backup_data_file_iso(FreefareTag tag, uint8_t file_no, uin
int int
mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, int32_t lower_limit, int32_t upper_limit, int32_t value, uint8_t limited_credit_enable) mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, int32_t lower_limit, int32_t upper_limit, int32_t value, uint8_t limited_credit_enable)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 18 + CMAC_LENGTH); BUFFER_INIT(cmd, 18 + CMAC_LENGTH);
@ -1416,9 +1529,10 @@ mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t commu
BUFFER_APPEND_LE(cmd, value, 4, sizeof(int32_t)); BUFFER_APPEND_LE(cmd, value, 4, sizeof(int32_t));
BUFFER_APPEND(cmd, limited_credit_enable); BUFFER_APPEND(cmd, limited_credit_enable);
char *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1434,6 +1548,8 @@ mifare_desfire_create_value_file(FreefareTag tag, uint8_t file_no, uint8_t commu
static int static int
create_file2(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records) create_file2(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 11 + CMAC_LENGTH); BUFFER_INIT(cmd, 11 + CMAC_LENGTH);
@ -1448,9 +1564,10 @@ create_file2(FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file
BUFFER_APPEND_LE(cmd, record_size, 3, sizeof(uint32_t)); BUFFER_APPEND_LE(cmd, record_size, 3, sizeof(uint32_t));
BUFFER_APPEND_LE(cmd, max_number_of_records, 3, sizeof(uint32_t)); BUFFER_APPEND_LE(cmd, max_number_of_records, 3, sizeof(uint32_t));
char *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1490,6 +1607,8 @@ mifare_desfire_create_cyclic_record_file_iso(FreefareTag tag, uint8_t file_no, u
int int
mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no) mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 2 + CMAC_LENGTH); BUFFER_INIT(cmd, 2 + CMAC_LENGTH);
@ -1500,7 +1619,8 @@ mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1511,7 +1631,6 @@ mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no)
return 0; return 0;
} }
/* /*
* Data manipulation commands. * Data manipulation commands.
*/ */
@ -1519,6 +1638,8 @@ mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no)
static ssize_t static ssize_t
read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t length, void *data, int cs) read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t length, void *data, int cs)
{ {
int rc;
size_t bytes_received = 0; size_t bytes_received = 0;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
@ -1599,7 +1720,10 @@ read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_
uint8_t *read_buffer = malloc(enciphered_data_length(tag, length * record_size, 0) + 1); uint8_t *read_buffer = malloc(enciphered_data_length(tag, length * record_size, 0) + 1);
do { do {
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0) {
free(read_buffer);
return rc;
}
size_t frame_bytes = BUFFER_SIZE(res) - 1; size_t frame_bytes = BUFFER_SIZE(res) - 1;
memcpy(read_buffer + bytes_received, res, frame_bytes); memcpy(read_buffer + bytes_received, res, frame_bytes);
@ -1640,6 +1764,8 @@ mifare_desfire_read_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size
static ssize_t static ssize_t
write_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t length, const void *data, int cs) write_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t length, const void *data, int cs)
{ {
int rc;
size_t bytes_left; size_t bytes_left;
size_t bytes_send = 0; size_t bytes_send = 0;
@ -1665,7 +1791,8 @@ write_data(FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size
size_t frame_bytes = MIN(bytes_left, __cmd_n - bytes_send); size_t frame_bytes = MIN(bytes_left, __cmd_n - bytes_send);
BUFFER_APPEND_BYTES(d, p + bytes_send, frame_bytes); BUFFER_APPEND_BYTES(d, p + bytes_send, frame_bytes);
DESFIRE_TRANSCEIVE(tag, d, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, d, __d_n, res, __res_size, &__res_n)) < 0)
return rc;
bytes_send += frame_bytes; bytes_send += frame_bytes;
@ -1719,6 +1846,8 @@ mifare_desfire_get_value(FreefareTag tag, uint8_t file_no, int32_t *value)
int int
mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, int cs) mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, int cs)
{ {
int rc;
if (!value) if (!value)
return errno = EINVAL, -1; return errno = EINVAL, -1;
@ -1733,7 +1862,8 @@ mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, in
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, cs | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, cs | CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY);
@ -1755,6 +1885,8 @@ mifare_desfire_credit(FreefareTag tag, uint8_t file_no, int32_t amount)
int int
mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs) mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_CS(cs); ASSERT_CS(cs);
@ -1766,7 +1898,8 @@ mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int c
BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t)); BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t));
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1787,6 +1920,8 @@ mifare_desfire_debit(FreefareTag tag, uint8_t file_no, int32_t amount)
int int
mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs) mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_CS(cs); ASSERT_CS(cs);
@ -1798,7 +1933,8 @@ mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs
BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t)); BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t));
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1819,6 +1955,8 @@ mifare_desfire_limited_credit(FreefareTag tag, uint8_t file_no, int32_t amount)
int int
mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs) mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
ASSERT_CS(cs); ASSERT_CS(cs);
@ -1830,7 +1968,8 @@ mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amoun
BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t)); BUFFER_APPEND_LE(cmd, amount, 4, sizeof(int32_t));
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 2, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1869,6 +2008,8 @@ mifare_desfire_read_records_ex(FreefareTag tag, uint8_t file_no, off_t offset, s
int int
mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no) mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 2 + CMAC_LENGTH); BUFFER_INIT(cmd, 2 + CMAC_LENGTH);
@ -1879,7 +2020,8 @@ mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1895,6 +2037,8 @@ mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no)
int int
mifare_desfire_commit_transaction(FreefareTag tag) mifare_desfire_commit_transaction(FreefareTag tag)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1 + CMAC_LENGTH); BUFFER_INIT(cmd, 1 + CMAC_LENGTH);
@ -1904,7 +2048,8 @@ mifare_desfire_commit_transaction(FreefareTag tag)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
@ -1918,6 +2063,8 @@ mifare_desfire_commit_transaction(FreefareTag tag)
int int
mifare_desfire_abort_transaction(FreefareTag tag) mifare_desfire_abort_transaction(FreefareTag tag)
{ {
int rc;
ASSERT_ACTIVE(tag); ASSERT_ACTIVE(tag);
BUFFER_INIT(cmd, 1 + CMAC_LENGTH); BUFFER_INIT(cmd, 1 + CMAC_LENGTH);
@ -1927,7 +2074,8 @@ mifare_desfire_abort_transaction(FreefareTag tag)
uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND); uint8_t *p = mifare_cryto_preprocess_data(tag, cmd, &__cmd_n, 0, MDCM_PLAIN | CMAC_COMMAND);
DESFIRE_TRANSCEIVE2(tag, p, __cmd_n, res); if ((rc = MIFARE_DESFIRE_TRANSCEIVE(tag, p, __cmd_n, res, __res_size, &__res_n)) < 0)
return rc;
ssize_t sn = __res_n; ssize_t sn = __res_n;
p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); p = mifare_cryto_postprocess_data(tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);

View file

@ -70,7 +70,7 @@ void
rol(uint8_t *data, const size_t len) rol(uint8_t *data, const size_t len)
{ {
if (len == 0) if (len == 0)
return; return;
uint8_t first = data[0]; uint8_t first = data[0];
for (size_t i = 0; i < len - 1; i++) { for (size_t i = 0; i < len - 1; i++) {
@ -83,7 +83,7 @@ void
lsl(uint8_t *data, size_t len) lsl(uint8_t *data, size_t len)
{ {
if (len == 0) if (len == 0)
return; return;
for (size_t n = 0; n < len - 1; n++) { for (size_t n = 0; n < len - 1; n++) {
data[n] = (data[n] << 1) | (data[n + 1] >> 7); data[n] = (data[n] << 1) | (data[n + 1] >> 7);