Skip to content

Commit

Permalink
mifare-ultralight: Added mifare_ultralightc_set_key()
Browse files Browse the repository at this point in the history
This new method sets the authentication key on a MIFARE Ultralight C
card, and is analogous to `ntag21x_set_key()`.
  • Loading branch information
darconeous committed Jan 6, 2018
1 parent 2bda6a0 commit 58ced25
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
1 change: 1 addition & 0 deletions libfreefare/freefare.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ int mifare_ultralight_read(FreefareTag tag, const MifareUltralightPageNumber p
int mifare_ultralight_write(FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data);

int mifare_ultralightc_authenticate(FreefareTag tag, const MifareDESFireKey key);
int mifare_ultralightc_set_key(FreefareTag tag, MifareDESFireKey key);
bool is_mifare_ultralight(FreefareTag tag);
bool is_mifare_ultralightc(FreefareTag tag);
bool is_mifare_ultralightc_on_reader(nfc_device *device, nfc_iso14443a_info nai);
Expand Down
52 changes: 52 additions & 0 deletions libfreefare/mifare_ultralight.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,58 @@ mifare_ultralightc_authenticate(FreefareTag tag, const MifareDESFireKey key)
return 0;
}

/*
* Set the authentication key for the provided MIFARE tag.
*/
int
mifare_ultralightc_set_key(FreefareTag tag, MifareDESFireKey key)
{
MifareUltralightPage data;

if (key->type != T_3DES) {
errno = EINVAL;
return -1;
}

data[0] = key->data[7];
data[1] = key->data[6];
data[2] = key->data[5];
data[3] = key->data[4];

if (mifare_ultralight_write(tag, 0x2C, data)<0) {
return -1;
}

data[0] = key->data[3];
data[1] = key->data[2];
data[2] = key->data[1];
data[3] = key->data[0];

if (mifare_ultralight_write(tag, 0x2D, data)<0) {
return -1;
}

data[0] = key->data[15];
data[1] = key->data[14];
data[2] = key->data[13];
data[3] = key->data[12];

if (mifare_ultralight_write(tag, 0x2E, data)<0) {
return -1;
}

data[0] = key->data[11];
data[1] = key->data[10];
data[2] = key->data[9];
data[3] = key->data[8];

if (mifare_ultralight_write(tag, 0x2F, data)<0) {
return -1;
}

return 0;
}

bool
is_mifare_ultralight(FreefareTag tag)
{
Expand Down
48 changes: 48 additions & 0 deletions test/test_mifare_ultralight.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,51 @@ test_mifare_ultralightc_authenticate(void)
cut_omit("mifare_ultralightc_authenticate() skipped on Ultralight");
}
}

void
test_mifare_ultralightc_set_key(void)
{
int res;
const uint8_t default_key_data[16] = { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 };
const uint8_t test_key_data[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0XEE, 0xFF };
MifareDESFireKey default_key;
MifareDESFireKey test_key;

if (is_mifare_ultralightc(tag)) {
default_key = mifare_desfire_3des_key_new(default_key_data);
test_key = mifare_desfire_3des_key_new(test_key_data);

// Change the key to the new key
res = mifare_ultralightc_set_key(tag, test_key);
cut_assert_equal_int(0, res, cut_message("mifare_ultralightc_set_key() failed"));

res = mifare_ultralight_disconnect(tag);
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_disconnect() failed"));

res = mifare_ultralight_connect(tag);
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_connect() failed"));

// Test the new key
res = mifare_ultralightc_authenticate(tag, test_key);
cut_assert_equal_int(0, res, cut_message("mifare_ultralightc_authenticate() failed"));

// Change the key back to the default key
res = mifare_ultralightc_set_key(tag, default_key);
cut_assert_equal_int(0, res, cut_message("mifare_ultralightc_set_key() failed"));

res = mifare_ultralight_disconnect(tag);
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_disconnect() failed"));

res = mifare_ultralight_connect(tag);
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_connect() failed"));

// Test the default key
res = mifare_ultralightc_authenticate(tag, default_key);
cut_assert_equal_int(0, res, cut_message("mifare_ultralightc_authenticate() failed"));

mifare_desfire_key_free(default_key);
mifare_desfire_key_free(test_key);
} else {
cut_omit("mifare_ultralightc_set_key() skipped on Ultralight");
}
}

0 comments on commit 58ced25

Please sign in to comment.