diff --git a/NEWS b/NEWS
index 848d6a2..f061c34 100644
--- a/NEWS
+++ b/NEWS
@@ -4,8 +4,9 @@ Changes between 0.2.3 and 0.3.0 [XX xxx XXXX]
mifare_desfire_authenticate_iso() and mifare_desfire_authenticate_aes().
*) Add support for 3K3DES and AES cryptographic operations.
*) New functions mifare_desfire_free_mem(),
- mifare_desfire_set_configuration(), mifare_desfire_get_card_uid(), for
- Mifare DESFire EV1 targets manipulation.
+ mifare_desfire_set_configuration(), mifare_desfire_set_default_key(),
+ mifare_desfire_get_card_uid(), for Mifare DESFire EV1 targets
+ manipulation.
*) Deprecate authentication information when deleting the currently selected
application
diff --git a/examples/Makefile.am b/examples/Makefile.am
index e8b042b..a1cf91b 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -6,6 +6,7 @@ AM_LDFLAGS = @LIBNFC_LIBS@
bin_PROGRAMS = mifare-classic-format \
mifare-classic-write-ndef \
mifare-desfire-access \
+ mifare-desfire-ev1-configure-default-key \
mifare-desfire-ev1-configure-random-uid \
mifare-desfire-format \
mifare-desfire-info \
@@ -20,6 +21,9 @@ mifare_classic_write_ndef_LDADD = -lnfc $(top_builddir)/libfreefare/libfreefare.
mifare_desfire_access_SOURCES = mifare-desfire-access.c
mifare_desfire_access_LDADD = -lnfc $(top_builddir)/libfreefare/libfreefare.la
+mifare_desfire_ev1_configure_default_key_SOURCES = mifare-desfire-ev1-configure-default-key.c
+mifare_desfire_ev1_configure_default_key_LDADD = -lnfc $(top_builddir)/libfreefare/libfreefare.la
+
mifare_desfire_ev1_configure_random_uid_SOURCES = mifare-desfire-ev1-configure-random-uid.c
mifare_desfire_ev1_configure_random_uid_LDADD = -lnfc $(top_builddir)/libfreefare/libfreefare.la
diff --git a/examples/mifare-desfire-ev1-configure-default-key.c b/examples/mifare-desfire-ev1-configure-default-key.c
new file mode 100644
index 0000000..bbb29fa
--- /dev/null
+++ b/examples/mifare-desfire-ev1-configure-default-key.c
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ *
+ * $Id$
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+uint8_t null_key_data[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+uint8_t new_key_data[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+
+#define NEW_KEY_VERSION 0x34;
+
+struct {
+ bool interactive;
+} configure_options = {
+ .interactive = true
+};
+
+void
+usage(char *progname)
+{
+ fprintf (stderr, "usage: %s [-y]\n", progname);
+ fprintf (stderr, "\nOptions:\n");
+ fprintf (stderr, " -y Do not ask for confirmation\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ int error = EXIT_SUCCESS;
+ nfc_device_t *device = NULL;
+ MifareTag *tags = NULL;
+
+ while ((ch = getopt (argc, argv, "hy")) != -1) {
+ switch (ch) {
+ case 'h':
+ usage(argv[0]);
+ exit (EXIT_SUCCESS);
+ break;
+ case 'y':
+ configure_options.interactive = false;
+ break;
+ default:
+ usage(argv[0]);
+ exit (EXIT_FAILURE);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ nfc_device_desc_t devices[8];
+ size_t device_count;
+
+ nfc_list_devices (devices, 8, &device_count);
+ if (!device_count)
+ errx (EXIT_FAILURE, "No NFC device found.");
+
+ for (size_t d = 0; (!error) && (d < device_count); d++) {
+ device = nfc_connect (&(devices[d]));
+ if (!device) {
+ warnx ("nfc_connect() failed.");
+ error = EXIT_FAILURE;
+ continue;
+ }
+
+ tags = freefare_get_tags (device);
+ if (!tags) {
+ nfc_disconnect (device);
+ errx (EXIT_FAILURE, "Error listing Mifare DESFire tags.");
+ }
+
+ for (int i = 0; (!error) && tags[i]; i++) {
+ if (DESFIRE != freefare_get_tag_type (tags[i]))
+ continue;
+
+ char *tag_uid = freefare_get_tag_uid (tags[i]);
+ char buffer[BUFSIZ];
+
+ printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
+ bool do_it = true;
+ int res;
+
+ if (configure_options.interactive) {
+ printf ("Change default key? [yN] ");
+ fgets (buffer, BUFSIZ, stdin);
+ do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
+ } else {
+ printf ("\n");
+ }
+
+ if (do_it) {
+
+ res = mifare_desfire_connect (tags[i]);
+ if (res < 0) {
+ warnx ("Can't connect to Mifare DESFire target.");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ MifareDESFireKey default_key = mifare_desfire_des_key_new_with_version (null_key_data);
+ res = mifare_desfire_authenticate (tags[i], 0, default_key);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_authenticate");
+ error = EXIT_FAILURE;
+ break;
+ }
+ mifare_desfire_key_free (default_key);
+
+ MifareDESFireKey new_key = mifare_desfire_des_key_new (new_key_data);
+ mifare_desfire_key_set_version (new_key, NEW_KEY_VERSION);
+ res = mifare_desfire_set_default_key (tags[i], new_key);
+ free (new_key);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_set_default_key");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ /*
+ * Perform some tests to ensure the function actually worked
+ * (it's hard to create a unit-test to do so).
+ */
+
+ MifareDESFireAID aid = mifare_desfire_aid_new (0x112233);
+ res = mifare_desfire_create_application (tags[i], aid, 0xFF, 1);
+
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_create_application");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ res = mifare_desfire_select_application (tags[i], aid);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_select_application");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ uint8_t version;
+ res = mifare_desfire_get_key_version (tags[i], 0, &version);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_get_key_version");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ if (version != NEW_KEY_VERSION) {
+ fprintf (stderr, "Wrong key version: %02x (expected %02x).\n");
+ error = EXIT_FAILURE;
+ /* continue */
+ }
+
+ new_key = mifare_desfire_des_key_new (new_key_data);
+ res = mifare_desfire_authenticate (tags[i], 0, new_key);
+ free (new_key);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_authenticate");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ free (aid);
+
+ /* Resetdefault settings */
+
+ res = mifare_desfire_select_application (tags[i], NULL);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_select_application");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ default_key = mifare_desfire_des_key_new (null_key_data);
+
+ res = mifare_desfire_authenticate (tags[i], 0, default_key);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_authenticate");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ res = mifare_desfire_set_default_key (tags[i], default_key);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_set_default_key");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ mifare_desfire_key_free (default_key);
+
+ /* Wipeout the card */
+
+ res = mifare_desfire_format_picc (tags[i]);
+ if (res < 0) {
+ freefare_perror (tags[i], "mifare_desfire_format_picc");
+ error = EXIT_FAILURE;
+ break;
+ }
+
+ mifare_desfire_disconnect (tags[i]);
+ }
+
+ free (tag_uid);
+ }
+
+ freefare_free_tags (tags);
+ nfc_disconnect (device);
+ }
+
+ exit (error);
+}
diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h
index 882d6e5..b655035 100644
--- a/libfreefare/freefare.h
+++ b/libfreefare/freefare.h
@@ -319,6 +319,7 @@ int mifare_desfire_format_picc (MifareTag tag);
int mifare_desfire_get_version (MifareTag tag, struct mifare_desfire_version_info *version_info);
int mifare_desfire_free_mem (MifareTag tag, uint32_t *size);
int mifare_desfire_set_configuration (MifareTag tag, bool disable_format, bool enable_random_uid);
+int mifare_desfire_set_default_key (MifareTag tag, MifareDESFireKey key);
int mifare_desfire_get_card_uid (MifareTag tag, char **uid);
int mifare_desfire_get_file_ids (MifareTag tag, uint8_t *files[], size_t *count);
int mifare_desfire_get_file_settings (MifareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
diff --git a/libfreefare/mifare_desfire.c b/libfreefare/mifare_desfire.c
index 66b424d..121e072 100644
--- a/libfreefare/mifare_desfire.c
+++ b/libfreefare/mifare_desfire.c
@@ -892,6 +892,43 @@ mifare_desfire_set_configuration (MifareTag tag, bool disable_format, bool enabl
return 0;
}
+int
+mifare_desfire_set_default_key (MifareTag tag, MifareDESFireKey key)
+{
+ ASSERT_ACTIVE (tag);
+ ASSERT_MIFARE_DESFIRE (tag);
+
+ BUFFER_INIT (cmd, 34);
+ BUFFER_INIT (res, 1 + CMAC_LENGTH);
+
+ BUFFER_APPEND (cmd, 0x5C);
+ BUFFER_APPEND (cmd, 0x01);
+ size_t key_data_length;
+ switch (key->type) {
+ case T_DES:
+ case T_3DES:
+ case T_AES:
+ key_data_length = 16;
+ break;
+ case T_3K3DES:
+ key_data_length = 24;
+ break;
+ }
+ BUFFER_APPEND_BYTES (cmd, key->data, key_data_length);
+ while (__cmd_n < 26)
+ BUFFER_APPEND (cmd, 0x00);
+ BUFFER_APPEND (cmd, mifare_desfire_key_get_version (key));
+
+ uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | ENC_COMMAND);
+
+ DESFIRE_TRANSCEIVE2 (tag, p, __cmd_n, res);
+
+ ssize_t sn = __res_n;
+ p = mifare_cryto_postprocess_data (tag, res, &sn, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY);
+
+ return 0;
+}
+
int
mifare_desfire_get_card_uid (MifareTag tag, char **uid)
{