Add an offset parameter to mifare_cryto_preprocess_data()
Some cryptographic operations are performed on the whole data frame and not only the payload with Mifare DESFire EV1. The solution for now is not perfect, (one new macro wrapping another big macro) but makes the code a bit easier to read, and with the MIFARE_DESFIRE macro rewriting as a function (at some point in the future), the whole should be bearable :-)
This commit is contained in:
parent
16ae154b42
commit
a643e9149d
3 changed files with 42 additions and 44 deletions
|
@ -116,7 +116,7 @@ typedef enum {
|
||||||
MD_RECEIVE
|
MD_RECEIVE
|
||||||
} MifareDirection;
|
} MifareDirection;
|
||||||
|
|
||||||
void *mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, int communication_settings);
|
void *mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
|
||||||
void *mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int communication_settings);
|
void *mifare_cryto_postprocess_data (MifareTag tag, void *data, ssize_t *nbytes, int communication_settings);
|
||||||
void mifare_cbc_des (MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareDirection direction, int mac);
|
void mifare_cbc_des (MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareDirection direction, int mac);
|
||||||
void rol (uint8_t *data, const size_t len);
|
void rol (uint8_t *data, const size_t len);
|
||||||
|
|
|
@ -155,14 +155,16 @@ static uint8_t __res[MAX_FRAME_SIZE];
|
||||||
* 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) \
|
#define DESFIRE_TRANSCEIVE(tag, msg, res) \
|
||||||
|
DESFIRE_TRANSCEIVE2 (tag, msg, __##msg##_n, res)
|
||||||
|
#define DESFIRE_TRANSCEIVE2(tag, msg, msg_len, res) \
|
||||||
do { \
|
do { \
|
||||||
size_t __len = 5; \
|
size_t __len = 5; \
|
||||||
errno = 0; \
|
errno = 0; \
|
||||||
__msg[1] = msg[0]; \
|
__msg[1] = msg[0]; \
|
||||||
if (__##msg##_n > 1) { \
|
if (msg_len > 1) { \
|
||||||
__len += __##msg##_n; \
|
__len += msg_len; \
|
||||||
__msg[4] = __##msg##_n - 1; \
|
__msg[4] = msg_len - 1; \
|
||||||
memcpy (__msg + 5, msg + 1, __##msg##_n - 1); \
|
memcpy (__msg + 5, msg + 1, msg_len - 1); \
|
||||||
} \
|
} \
|
||||||
__msg[__len-1] = 0x00; \
|
__msg[__len-1] = 0x00; \
|
||||||
MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK; \
|
MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK; \
|
||||||
|
@ -999,24 +1001,25 @@ write_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_
|
||||||
ASSERT_MIFARE_DESFIRE (tag);
|
ASSERT_MIFARE_DESFIRE (tag);
|
||||||
ASSERT_CS (cs);
|
ASSERT_CS (cs);
|
||||||
|
|
||||||
BUFFER_INIT (cmd, MAX_FRAME_SIZE);
|
BUFFER_INIT (cmd, 8 + length);
|
||||||
BUFFER_INIT (res, 1);
|
BUFFER_INIT (res, 1);
|
||||||
|
|
||||||
BUFFER_APPEND (cmd, command);
|
BUFFER_APPEND (cmd, command);
|
||||||
BUFFER_APPEND (cmd, file_no);
|
BUFFER_APPEND (cmd, file_no);
|
||||||
BUFFER_APPEND_LE (cmd, offset, 3, sizeof (off_t));
|
BUFFER_APPEND_LE (cmd, offset, 3, sizeof (off_t));
|
||||||
BUFFER_APPEND_LE (cmd, length, 3, sizeof (size_t));
|
BUFFER_APPEND_LE (cmd, length, 3, sizeof (size_t));
|
||||||
|
BUFFER_APPEND_BYTES (cmd, data, length);
|
||||||
|
|
||||||
p = mifare_cryto_preprocess_data (tag, data, &length, cs);
|
p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 8, cs);
|
||||||
|
|
||||||
bytes_left = FRAME_PAYLOAD_SIZE - 8;
|
BUFFER_INIT(d, FRAME_PAYLOAD_SIZE);
|
||||||
|
bytes_left = FRAME_PAYLOAD_SIZE;
|
||||||
|
|
||||||
while (bytes_send < length) {
|
while (bytes_send < __cmd_n) {
|
||||||
size_t frame_bytes = MIN(bytes_left, length - bytes_send);
|
size_t frame_bytes = MIN(bytes_left, __cmd_n - bytes_send);
|
||||||
|
BUFFER_APPEND_BYTES (d, (uint8_t *) p + bytes_send, frame_bytes);
|
||||||
|
|
||||||
BUFFER_APPEND_BYTES (cmd, (uint8_t *)p + bytes_send, frame_bytes);
|
DESFIRE_TRANSCEIVE (tag, d, res);
|
||||||
|
|
||||||
DESFIRE_TRANSCEIVE (tag, cmd, res);
|
|
||||||
|
|
||||||
bytes_send += frame_bytes;
|
bytes_send += frame_bytes;
|
||||||
|
|
||||||
|
@ -1024,12 +1027,15 @@ write_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// PICC returned 0xAF and expects more data
|
// PICC returned 0xAF and expects more data
|
||||||
BUFFER_CLEAR (cmd);
|
BUFFER_CLEAR (d);
|
||||||
BUFFER_APPEND (cmd, 0xAF);
|
BUFFER_APPEND (d, 0xAF);
|
||||||
bytes_left = FRAME_PAYLOAD_SIZE - 1;
|
bytes_left = FRAME_PAYLOAD_SIZE - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0x00 != res[__res_n-1]) {
|
if (0x00 == res[__res_n-1]) {
|
||||||
|
// Remove header length
|
||||||
|
bytes_send -= 8;
|
||||||
|
} else {
|
||||||
// 0xAF (additionnal Frame) failure can happen here (wrong crypto method).
|
// 0xAF (additionnal Frame) failure can happen here (wrong crypto method).
|
||||||
MIFARE_DESFIRE (tag)->last_picc_error = res[__res_n-1];
|
MIFARE_DESFIRE (tag)->last_picc_error = res[__res_n-1];
|
||||||
bytes_send = -1;
|
bytes_send = -1;
|
||||||
|
@ -1109,16 +1115,12 @@ mifare_desfire_credit_ex (MifareTag tag, uint8_t file_no, int32_t amount, int cs
|
||||||
BUFFER_INIT (cmd, 10);
|
BUFFER_INIT (cmd, 10);
|
||||||
BUFFER_INIT (res, 1);
|
BUFFER_INIT (res, 1);
|
||||||
|
|
||||||
BUFFER_INIT (data, 4);
|
|
||||||
BUFFER_APPEND_LE (data, amount, 4, sizeof (int32_t));
|
|
||||||
|
|
||||||
BUFFER_APPEND (cmd, 0x0C);
|
BUFFER_APPEND (cmd, 0x0C);
|
||||||
BUFFER_APPEND (cmd, file_no);
|
BUFFER_APPEND (cmd, file_no);
|
||||||
size_t n = 4;
|
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (int32_t));
|
||||||
void *d = mifare_cryto_preprocess_data (tag, data, &n, cs);
|
uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 2, cs);
|
||||||
BUFFER_APPEND_BYTES (cmd, d, n);
|
|
||||||
|
|
||||||
DESFIRE_TRANSCEIVE (tag, cmd, res);
|
DESFIRE_TRANSCEIVE2 (tag, p, __cmd_n, res);
|
||||||
|
|
||||||
cached_file_settings_current[file_no] = false;
|
cached_file_settings_current[file_no] = false;
|
||||||
|
|
||||||
|
@ -1140,16 +1142,12 @@ mifare_desfire_debit_ex (MifareTag tag, uint8_t file_no, int32_t amount, int cs)
|
||||||
BUFFER_INIT (cmd, 10);
|
BUFFER_INIT (cmd, 10);
|
||||||
BUFFER_INIT (res, 1);
|
BUFFER_INIT (res, 1);
|
||||||
|
|
||||||
BUFFER_INIT (data, 4);
|
|
||||||
BUFFER_APPEND_LE (data, amount, 4, sizeof (int32_t));
|
|
||||||
|
|
||||||
BUFFER_APPEND (cmd, 0xDC);
|
BUFFER_APPEND (cmd, 0xDC);
|
||||||
BUFFER_APPEND (cmd, file_no);
|
BUFFER_APPEND (cmd, file_no);
|
||||||
size_t n = 4;
|
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (int32_t));
|
||||||
void *d = mifare_cryto_preprocess_data (tag, data, &n, cs);
|
uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 2, cs);
|
||||||
BUFFER_APPEND_BYTES (cmd, d, n);
|
|
||||||
|
|
||||||
DESFIRE_TRANSCEIVE (tag, cmd, res);
|
DESFIRE_TRANSCEIVE2 (tag, p, __cmd_n, res);
|
||||||
|
|
||||||
cached_file_settings_current[file_no] = false;
|
cached_file_settings_current[file_no] = false;
|
||||||
|
|
||||||
|
@ -1171,16 +1169,12 @@ mifare_desfire_limited_credit_ex (MifareTag tag, uint8_t file_no, int32_t amount
|
||||||
BUFFER_INIT (cmd, 10);
|
BUFFER_INIT (cmd, 10);
|
||||||
BUFFER_INIT (res, 1);
|
BUFFER_INIT (res, 1);
|
||||||
|
|
||||||
BUFFER_INIT (data, 4);
|
|
||||||
BUFFER_APPEND_LE (data, amount, 4, sizeof (int32_t));
|
|
||||||
|
|
||||||
BUFFER_APPEND (cmd, 0x1C);
|
BUFFER_APPEND (cmd, 0x1C);
|
||||||
BUFFER_APPEND (cmd, file_no);
|
BUFFER_APPEND (cmd, file_no);
|
||||||
size_t n = 4;
|
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (int32_t));
|
||||||
void *d = mifare_cryto_preprocess_data (tag, data, &n, cs);
|
uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 2, cs);
|
||||||
BUFFER_APPEND_BYTES (cmd, d, n);
|
|
||||||
|
|
||||||
DESFIRE_TRANSCEIVE (tag, cmd, res);
|
DESFIRE_TRANSCEIVE2 (tag, p, __cmd_n, res);
|
||||||
|
|
||||||
cached_file_settings_current[file_no] = false;
|
cached_file_settings_current[file_no] = false;
|
||||||
|
|
||||||
|
|
|
@ -131,11 +131,15 @@ assert_crypto_buffer_size (MifareTag tag, size_t nbytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, int communication_settings)
|
mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings)
|
||||||
{
|
{
|
||||||
void *res;
|
void *res;
|
||||||
uint8_t mac[4];
|
uint8_t mac[4];
|
||||||
size_t edl, mdl;
|
size_t edl, mdl;
|
||||||
|
MifareDESFireKey key = MIFARE_DESFIRE (tag)->session_key;
|
||||||
|
|
||||||
|
if (!key)
|
||||||
|
return data;
|
||||||
|
|
||||||
switch (communication_settings) {
|
switch (communication_settings) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -143,7 +147,7 @@ mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, int com
|
||||||
res = data;
|
res = data;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
edl = padded_data_length (*nbytes, key_block_size (MIFARE_DESFIRE (tag)->session_key));
|
edl = padded_data_length (*nbytes - offset, key_block_size (MIFARE_DESFIRE (tag)->session_key)) + offset;
|
||||||
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
|
@ -152,11 +156,11 @@ mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, int com
|
||||||
// ... and 0 padding
|
// ... and 0 padding
|
||||||
bzero ((uint8_t *)res + *nbytes, edl - *nbytes);
|
bzero ((uint8_t *)res + *nbytes, edl - *nbytes);
|
||||||
|
|
||||||
mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, MIFARE_DESFIRE (tag)->ivect, res, edl, MD_SEND, 1);
|
mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, MIFARE_DESFIRE (tag)->ivect, (uint8_t *) res + offset, edl - offset, MD_SEND, 1);
|
||||||
|
|
||||||
memcpy (mac, (uint8_t *)res + edl - 8, 4);
|
memcpy (mac, (uint8_t *)res + edl - 8, 4);
|
||||||
|
|
||||||
mdl = maced_data_length (MIFARE_DESFIRE (tag)->session_key, *nbytes);
|
mdl = maced_data_length (MIFARE_DESFIRE (tag)->session_key, *nbytes - offset) + offset;
|
||||||
if (!(res = assert_crypto_buffer_size (tag, mdl)))
|
if (!(res = assert_crypto_buffer_size (tag, mdl)))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
|
@ -167,20 +171,20 @@ mifare_cryto_preprocess_data (MifareTag tag, void *data, size_t *nbytes, int com
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
edl = enciphered_data_length (MIFARE_DESFIRE (tag)->session_key, *nbytes);
|
edl = enciphered_data_length (MIFARE_DESFIRE (tag)->session_key, *nbytes - offset) + offset;
|
||||||
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
// Fill in the crypto buffer with data ...
|
// Fill in the crypto buffer with data ...
|
||||||
memcpy (res, data, *nbytes);
|
memcpy (res, data, *nbytes);
|
||||||
// ... CRC ...
|
// ... CRC ...
|
||||||
iso14443a_crc_append (res, *nbytes);
|
iso14443a_crc_append ((uint8_t *)res + offset, *nbytes - offset);
|
||||||
// ... and 0 padding
|
// ... and 0 padding
|
||||||
bzero ((uint8_t *)(res) + *nbytes + 2, edl - *nbytes - 2);
|
bzero ((uint8_t *)(res) + *nbytes + 2, edl - *nbytes - 2);
|
||||||
|
|
||||||
*nbytes = edl;
|
*nbytes = edl;
|
||||||
|
|
||||||
mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, MIFARE_DESFIRE (tag)->ivect, res, *nbytes, MD_SEND, 0);
|
mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, MIFARE_DESFIRE (tag)->ivect, (uint8_t *) res + offset, *nbytes - offset, MD_SEND, 0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Reference in a new issue