diff --git a/NEWS b/NEWS index f061c34..07b4a5f 100644 --- a/NEWS +++ b/NEWS @@ -5,8 +5,8 @@ Changes between 0.2.3 and 0.3.0 [XX xxx XXXX] *) Add support for 3K3DES and AES cryptographic operations. *) New functions mifare_desfire_free_mem(), mifare_desfire_set_configuration(), mifare_desfire_set_default_key(), - mifare_desfire_get_card_uid(), for Mifare DESFire EV1 targets - manipulation. + mifare_desfire_set_ats(), 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 a1cf91b..c92abed 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-ats \ mifare-desfire-ev1-configure-default-key \ mifare-desfire-ev1-configure-random-uid \ mifare-desfire-format \ @@ -21,6 +22,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_ats_SOURCES = mifare-desfire-ev1-configure-ats.c +mifare_desfire_ev1_configure_ats_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 diff --git a/examples/mifare-desfire-ev1-configure-ats.c b/examples/mifare-desfire-ev1-configure-ats.c new file mode 100644 index 0000000..3be4913 --- /dev/null +++ b/examples/mifare-desfire-ev1-configure-ats.c @@ -0,0 +1,153 @@ +/*- + * 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_ats[] = { 0x06, 0x75, 0x77, 0x81, 0x02, 0x42 }; + +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 (dangerous)\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 ATS? [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); + + res = mifare_desfire_set_ats (tags[i], new_ats); + if (res < 0) { + freefare_perror (tags[i], "mifare_desfire_set_ats"); + error = EXIT_FAILURE; + break; + } + + mifare_desfire_disconnect (tags[i]); + + } + + free (tag_uid); + } + + freefare_free_tags (tags); + nfc_disconnect (device); + } + + exit (error); +} /* main() */ + diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h index b655035..3c1e8c8 100644 --- a/libfreefare/freefare.h +++ b/libfreefare/freefare.h @@ -320,6 +320,7 @@ int mifare_desfire_get_version (MifareTag tag, struct mifare_desfire_version_i 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_set_ats (MifareTag tag, uint8_t *ats); 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 121e072..211aba8 100644 --- a/libfreefare/mifare_desfire.c +++ b/libfreefare/mifare_desfire.c @@ -929,6 +929,40 @@ mifare_desfire_set_default_key (MifareTag tag, MifareDESFireKey key) return 0; } +int +mifare_desfire_set_ats (MifareTag tag, uint8_t *ats) +{ + ASSERT_ACTIVE (tag); + ASSERT_MIFARE_DESFIRE (tag); + + BUFFER_INIT (cmd, 34); + BUFFER_INIT (res, 1 + CMAC_LENGTH); + + BUFFER_APPEND (cmd, 0x5C); + BUFFER_APPEND (cmd, 0x02); + BUFFER_APPEND_BYTES (cmd, ats, *ats); + switch (MIFARE_DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + iso14443a_crc_append (cmd + 2 , __cmd_n - 2); + __cmd_n += 2; + break; + case AS_NEW: + desfire_crc32_append (cmd, __cmd_n); + __cmd_n += 4; + break; + } + BUFFER_APPEND (cmd, 0x80); + + uint8_t *p = mifare_cryto_preprocess_data (tag, cmd, &__cmd_n, 2, MDCM_ENCIPHERED | NO_CRC | 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) {