From 58ced259786b76882ab9f208f2041ed5f890366f Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Fri, 5 Jan 2018 22:20:38 -0800 Subject: [PATCH] mifare-ultralight: Added mifare_ultralightc_set_key() This new method sets the authentication key on a MIFARE Ultralight C card, and is analogous to `ntag21x_set_key()`. --- libfreefare/freefare.h | 1 + libfreefare/mifare_ultralight.c | 52 +++++++++++++++++++++++++++++++++ test/test_mifare_ultralight.c | 48 ++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h index d84ed08..85b1668 100644 --- a/libfreefare/freefare.h +++ b/libfreefare/freefare.h @@ -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); diff --git a/libfreefare/mifare_ultralight.c b/libfreefare/mifare_ultralight.c index 5562fb0..f85b478 100644 --- a/libfreefare/mifare_ultralight.c +++ b/libfreefare/mifare_ultralight.c @@ -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) { diff --git a/test/test_mifare_ultralight.c b/test/test_mifare_ultralight.c index fdea38b..3fde28e 100644 --- a/test/test_mifare_ultralight.c +++ b/test/test_mifare_ultralight.c @@ -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"); + } +}