Exemplo n.º 1
0
/*
 * Free the provided tag.
 */
void
mifare_desfire_tag_free (MifareTag tag)
{
    free (MIFARE_DESFIRE (tag)->session_key);
    free (MIFARE_DESFIRE (tag)->last_pcd_error);
    free (MIFARE_DESFIRE (tag)->crypto_buffer);
    free (tag);
}
Exemplo n.º 2
0
int
mifare_desfire_change_key (MifareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);
    ASSERT_AUTHENTICATED (tag);

    BUFFER_INIT (cmd, 1+1+24);
    BUFFER_INIT (res, 1);

    BUFFER_APPEND (cmd, 0xC4);
    BUFFER_APPEND (cmd, key_no);

    uint8_t data[24];

    if ((MIFARE_DESFIRE (tag)->authenticated_key_no != key_no) /* FIXME && (ChangeKey key != 0x0E)*/) {
	if (old_key) {
	    memcpy (data, old_key->data, 16);
	} else {
	    bzero (data, 16);
	}
	for (int n=0; n<16; n++) {
	    data[n] ^= new_key->data[n];
	}
	// Append XORed data CRC
	iso14443a_crc (data, 16, data+16);
	// Append new key CRC
	iso14443a_crc (new_key->data, 16, data+18);
	// Padding
	for (int n=20; n<24; n++) {
	    data[n] = 0x00;
	}
    } else {
	memcpy (data, new_key->data, 16);
	// Append new key CRC
	iso14443a_crc (data, 16, data+16);

	// Padding
	for (int n=18; n<24; n++) {
	    data[n] = 0x00;
	}
    }

    mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, data, 24, MD_SEND, 0);

    BUFFER_APPEND_BYTES (cmd, data, 24);

    DESFIRE_TRANSCEIVE (tag, cmd, res);

    return 0;
}
Exemplo n.º 3
0
/*
 * Terminate connection with the provided tag.
 */
int
mifare_desfire_disconnect (MifareTag tag)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    free (MIFARE_DESFIRE (tag)->session_key);
    MIFARE_DESFIRE(tag)->session_key = NULL;

    if (nfc_initiator_deselect_target (tag->device)) {
	tag->active = 0;
    }
    return 0;
}
Exemplo n.º 4
0
int
madame_soleil_get_write_communication_settings (MifareTag tag, uint8_t file_no)
{
    // FIXME: It might be forbiden to get file settings.
    struct mifare_desfire_file_settings settings;
    if (mifare_desfire_get_file_settings (tag, file_no, &settings))
	return -1;

    if ((MIFARE_DESFIRE (tag)->authenticated_key_no == MDAR_WRITE (settings.access_rights)) ||
	(MIFARE_DESFIRE (tag)->authenticated_key_no == MDAR_READ_WRITE (settings.access_rights)))
	return settings.communication_settings;
    else
	return 0;
}
Exemplo n.º 5
0
int
mifare_desfire_change_key_settings (MifareTag tag, uint8_t settings)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);
    ASSERT_AUTHENTICATED (tag);

    BUFFER_INIT (cmd, 9);
    BUFFER_INIT (res, 1);

    BUFFER_APPEND (cmd, 0x54);

    uint8_t data[8];

    data[0] = settings;
    iso14443a_crc (data, 1, data + 1);
    bzero (data+3, 5);

    mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, data, 8, MD_SEND, 0);

    BUFFER_APPEND_BYTES (cmd, data, 8);

    DESFIRE_TRANSCEIVE (tag, cmd, res);

    return 0;
}
Exemplo n.º 6
0
uint8_t
mifare_desfire_last_picc_error (MifareTag tag)
{
    if (tag->tag_info->type != DESFIRE)
	return 0;

    return MIFARE_DESFIRE (tag)->last_picc_error;
}
Exemplo n.º 7
0
const char *
freefare_strerror (FreefareTag tag)
{
    const char *p = "Unknown error";
    if (nfc_device_get_last_error (tag->device) < 0) {
        p = nfc_strerror (tag->device);
    } else {
        if (tag->tag_info->type == MIFARE_DESFIRE) {
            if (MIFARE_DESFIRE (tag)->last_pcd_error) {
                p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_pcd_error);
            } else if (MIFARE_DESFIRE (tag)->last_picc_error) {
                p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_picc_error);
            }
        }
    }
    return p;
}
Exemplo n.º 8
0
/*
 * Establish connection to the provided tag.
 */
int
mifare_desfire_connect (MifareTag tag)
{
    ASSERT_INACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    nfc_target_info_t pnti;
    if (nfc_initiator_select_passive_target (tag->device, NM_ISO14443A_106, tag->info.abtUid, 7, &pnti)) {
	tag->active = 1;
	free (MIFARE_DESFIRE (tag)->session_key);
	MIFARE_DESFIRE (tag)->session_key = NULL;
	MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
	MIFARE_DESFIRE (tag)->last_pcd_error = NULL;
	MIFARE_DESFIRE (tag)->authenticated_key_no = NOT_YET_AUTHENTICATED;
    } else {
	errno = EIO;
	return -1;
    }
    return 0;
}
Exemplo n.º 9
0
/*
 * Allocates and initialize a MIFARE DESFire tag.
 */
MifareTag
mifare_desfire_tag_new (uint32_t aFd)
{
	nfc_iso14443a_info_t dummy_info;
    MifareTag tag;
    if ((tag= malloc (sizeof (struct mifare_desfire_tag)))) {
	MIFARE_DESFIRE (tag)->last_picc_error = OPERATION_OK;
	MIFARE_DESFIRE (tag)->last_pcd_error = NULL;
	MIFARE_DESFIRE (tag)->session_key = NULL;
	MIFARE_DESFIRE (tag)->crypto_buffer = NULL;
	MIFARE_DESFIRE (tag)->crypto_buffer_size = 0;
	
	device.ui8TxBits = aFd;
	tag->device = &device;
	tag->info = dummy_info;
	tag->active = 0;
	tag->tag_info = supported_tags_jim + 3;
    }
    return tag;
}
Exemplo n.º 10
0
static ssize_t
write_data (MifareTag tag, uint8_t command, uint8_t file_no, off_t offset, size_t length, void *data, int cs)
{
    size_t bytes_left;
    size_t bytes_send = 0;

    void *p = data;

    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    BUFFER_INIT (cmd, MAX_FRAME_SIZE);
    BUFFER_INIT (res, 1);

    BUFFER_APPEND (cmd, command);
    BUFFER_APPEND (cmd, file_no);
    BUFFER_APPEND_LE (cmd, offset, 3, sizeof (off_t));
    BUFFER_APPEND_LE (cmd, length, 3, sizeof (size_t));

    p = mifare_cryto_preprocess_data (tag, data, &length, cs);

    bytes_left = 52;

    while (bytes_send < length) {
	size_t frame_bytes = MIN(bytes_left, length - bytes_send);

	BUFFER_APPEND_BYTES (cmd, (uint8_t *)p + bytes_send, frame_bytes);

	DESFIRE_TRANSCEIVE (tag, cmd, res);

	bytes_send += frame_bytes;

	if (0x00 == res[0])
	    break;

	// PICC returned 0xAF and expects more data
	BUFFER_CLEAR (cmd);
	BUFFER_APPEND (cmd, 0xAF);
	bytes_left = 0x59;
    }

    if (0x00 != res[0]) {
	// 0xAF (additionnal Frame) failure can happen here (wrong crypto method).
	MIFARE_DESFIRE (tag)->last_picc_error = res[0];
	bytes_send = -1;
    }

    return bytes_send;
}
Exemplo n.º 11
0
int
mifare_desfire_change_file_settings (MifareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    // TODO: Use a current application files settings cache.
    struct mifare_desfire_file_settings settings;
    int res = mifare_desfire_get_file_settings (tag, file_no, &settings);
    if (res < 0)
	return res;

    if (MDAR_CHANGE_AR(settings.access_rights) == MDAR_FREE) {
    BUFFER_INIT (cmd, 5);
    BUFFER_INIT (res, 1);

    BUFFER_APPEND (cmd, 0x5F);
    BUFFER_APPEND (cmd, file_no);
    BUFFER_APPEND (cmd, communication_settings);
    BUFFER_APPEND_LE (cmd, access_rights, 2, sizeof (uint16_t));

    DESFIRE_TRANSCEIVE (tag, cmd, res);
    } else {
	BUFFER_INIT (cmd, 10);
	BUFFER_INIT (res, 1);

	uint8_t data[8];

	BUFFER_APPEND (cmd, 0x5F);
	BUFFER_APPEND (cmd, file_no);

	data[0] = communication_settings;
	uint16_t le_ar = htole16 (access_rights);
	memcpy (data + 1, &le_ar, sizeof (le_ar));
	iso14443a_crc (data, 3, data+3);
	bzero (data + 5, 3);
	mifare_cbc_des (MIFARE_DESFIRE (tag)->session_key, data, 8, MD_SEND, 0);

	BUFFER_APPEND_BYTES (cmd, data, 8);

	DESFIRE_TRANSCEIVE (tag, cmd, res);
    }

    return 0;
}
Exemplo n.º 12
0
int
mifare_desfire_authenticate (MifareTag tag, uint8_t key_no, MifareDESFireKey key)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    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;

    BUFFER_INIT (cmd1, 2);
    BUFFER_INIT (res, 9);

    BUFFER_APPEND (cmd1, 0x0A);
    BUFFER_APPEND (cmd1, key_no);

    DESFIRE_TRANSCEIVE (tag, cmd1, res);

    uint8_t PICC_E_RndB[8];
    memcpy (PICC_E_RndB, res+1, 8);

    uint8_t PICC_RndB[8];
    memcpy (PICC_RndB, PICC_E_RndB, 8);
    mifare_cbc_des (key, PICC_RndB, 8, MD_RECEIVE, 0);

    uint8_t PCD_RndA[8];
    DES_random_key ((DES_cblock*)&PCD_RndA);

    uint8_t PCD_r_RndB[8];
    memcpy (PCD_r_RndB, PICC_RndB, 8);
    rol8 (PCD_r_RndB);

    uint8_t token[16];
    memcpy (token, PCD_RndA, 8);
    memcpy (token+8, PCD_r_RndB, 8);

    mifare_cbc_des (key, token, 16, MD_SEND, 0);

    BUFFER_INIT (cmd2, 17);

    BUFFER_APPEND (cmd2, 0xAF);
    BUFFER_APPEND_BYTES (cmd2, token, 16);

    DESFIRE_TRANSCEIVE (tag, cmd2, res);

    uint8_t PICC_E_RndA_s[8];
    memcpy (PICC_E_RndA_s, res+1, 8);

    uint8_t PICC_RndA_s[8];
    memcpy (PICC_RndA_s, PICC_E_RndA_s, 8);
    mifare_cbc_des (key, PICC_RndA_s, 8, MD_RECEIVE, 0);

    uint8_t PCD_RndA_s[8];
    memcpy (PCD_RndA_s, PCD_RndA, 8);
    rol8 (PCD_RndA_s);


    if (0 != memcmp (PCD_RndA_s, PICC_RndA_s, 8)) {
	    printf ("PCD_RndA_s != PICC_RndA_s");
		return -1;
    }

    MIFARE_DESFIRE (tag)->authenticated_key_no = key_no;
    MIFARE_DESFIRE (tag)->session_key = mifare_desfire_session_key_new (PCD_RndA, PICC_RndB, key);

    return 0;
}
Exemplo n.º 13
0
uint8_t
mifare_desfire_get_last_error (MifareTag tag)
{
    return MIFARE_DESFIRE (tag)->last_picc_error;
}