Mifare DESFire EV3 — a beginner tutorial (Android Java) using the DESFire for Android tools.

AndroidCrypto
13 min readFeb 18, 2024

--

Some days ago I was asked if there are tutorials available that show how to work with a Mifare DESFire NFC card *), but there is nothing available in the internet. As the protocol for accessing this NFC card type is more complicated compared to other tags. I’m very happy that Thomas Skjølberg provided the library Desfire for Android tools that makes the work much easier.

*) Mifare DESFire is a registered trademark of NXP B.V..

The Desfire for Android tools library provides a sample app that acts as a card reader, but there is no writing to the tag available. What is awaiting you in this tutorial and the accompanying project (the full code is available, see the link at the end) ?

These points are covered by the tutorial:

  • connect to the tag;
  • list, select, create and delete an application on the tag
  • list, select, create and delete a Standard file on the tag
  • authenticate with an application key
  • read and write to a Standard file
  • get the application key settings and file settings
  • obtain the tag version information, free memory and the card UID
  • format the tag

The tutorial app works with AES and DES key based applications and is supporting the 3 available communication modes (Plain, MACed and Encrypted).

Here is a short overview about about a DESFire EV3 tag. The tag has a capacity of 2K, 4K or 8K bytes and is the 4th generation of this tag family. The bad news are, that the usual way of reading the data sheet is much more complicated, because the full data sheet is available under a Non Disclosure Agreement (NDA) only. Fortunately the tags are downwards compatible to the very first generation and some, few documents are accessible that describe the data structure required for the communication. All of the commands and example shown in this tutorial will work on generations EV1 and EV2 as well.

The data on the tag is structured as follows: Starting from the tags “root” folder (named Master Application) there are Applications — think of a “folder” in a filesystem. Each application has an individual set of 14 application keys (can be AES-128 or DES keys). Within the application you find Files of 5 file types:

  • Standard File (e.g. used for static data like a employee ID)
  • Backup File (like a Standard File but with a “Commit” feature that allows for secure storage of data, e.g. a changeable user password)
  • Value File (storing changeable value information, e.g. the amount on a canteen payment card)
  • Linear Record File (storing a defined number of records, e.g. collecting of goodies)
  • Cyclic Record File (like a Linear Record file but this file doesn’t get “full” but the oldest entry gets overwritten by a new entry, e.g. for a log file).

This tutorial will work with Standard Files only, but the library is been able to work with all file types. Just as a note: starting with generation EV2 a Transaction MAC File type is available, but there is not much information available and not supported by DESFire Tools for Android.

The access to a file can be restricted by a proceeding authentication, a “free” access or “no access”. The library and this app are using the “Legacy” authentication (for DES keys) and “AES” authentication when using AES keys. Each file has it’s own Communication Mode:

  • Plain: all data transfer between the NFC tag and the NFC reader is done in plain
  • MACed: like in Plain mode the communication is is readable but secured by an appended MAC
  • Encrypted: the communication is not visible be anyone, but only who posses the used key is been able to read the data.

The sample app will work with all communication modes.

Let’s start with our journey through this tag:

  1. connect to the tag: the tag is using the “IsoDep” class to communicate with an Android device. It is compliant to all 4 levels of ISO/IEC 14443A and uses optional ISO/IEC 7816–4 commands. The app is using the NFC Reader Mode that allows a defined access to the tag (not the intent based connections).
  2. List the applications on the tag: an application is named by it’s 3 byte long identifier (Application Identifier, “AID”) and a list of these AID can be obtained by sending the command “6A: Get Application IDs” to the tag. On a tag with factory settings this list is accessible without proceeding authentication.
  3. For accessing a specific application we have to Select an application (command “5A: Select Application”) by it’s AID or an option “Datafile name” (“DF name”).

4. The Creation of an application needs 3 parameters: the AID, a Key Settings Byte (defines settings in the application) and an “Application Settings Byte” (defines type and number of authentication keys). A new application is created by the “CA: Create Application” command.

5. An application is deleted by the command “DA: Delete Application” that just needs the AID. Please note: the deletion of an application does not release the space on the tag.

6. after we selected an application we are been able to List all available Files within this application using the command “6F: Get FileIDs”.

7. For accessing a specific file we do NOT have to a Select a File command as for the following commands we use a file number (“File ID”) to use the file.

8. Create a new Standard Data File: we do need 4 parameter in total to create the file: a 1 byte long File ID (numbers 00 to 1F), a Communication Mode Byte, the File Access Rights Bytes (2 bytes) and the File Size (3 bytes). In my sample app I’m using a fixed File Access Rights scheme (see separate point below). The File ID is given by the selector, the Communication Mode can be Plain, MACed or Encrypted and the File Size is directly entered. The command is “CD: Create StdDataFile”.

9. To write data to the Standard File we use the command “3D: Write Data” that requires 4 parameter: the File ID, the “Offset” ( an offset means the position we are beginning to write to the file, 0 means beginning at start of file), the Length of data and the Data itself. Note: before writing to the file you need to authenticate with a “Write Access Rights” key (see below).

10. The next command to Read Data from a Standard File using the command ”BD: Read Data” requires 3 parameter: a File ID, a offset and a length parameter (see Write Data). The tutorial app is always reading the complete file. Note: before reading from the file you have to authenticate with a “Read Access Rights” key (see below).

11. For the Deletion of a File you need the File ID as a single parameter that is used in command “DF: DeleteFile”. Please note: the deletion of a file does not release the space on the tag.

12. Before talking about the last commands I’m focusing on the Access Rights Scheme. A file can be set to a “free access” for reading or writing, means when a file has a free read access everyone can access the data of the file (read access). If a file has a “no access” read no one can read the file (makes no sense, really ?). The same applies to the write part: a free write access enables everyone to write to the file, a no write access denies any writing access to the file.

Beneath these rights you can define a separate authentication key that is needed for e.g. a read or write access. This allows e.g. to use the “Write Access Rights” key within the Human Rights department (“HR”) to store the employee ID on the tag, but the NFC reader at the door opener just gets the “Read Access Rights” key. Additionally the file has a combined “Read and Write Access Rights” key that allows reading and writing with one authentication key.

But that’s not all, the file has 2 more access rights keys. A very important key is the “Application Master Access Rights” key: to change any keys it is important to authenticate with this key (if not changed in the application key settings). The last authentication key is the “Change Access Rights” key (“CAR”) if you want to exchange the key numbers for an access right.

At this point we do know about the authentication keys, but how to run the “mutual 3-pass authentication” ? We will exchange data between the reader and the NFC device 3 times subsequently for one (good) reason or question:

How to check that two parties know a key without exchanging this key ?

Maybe you are surprised now, but that is agood cryptography workflow: do not exchange secret keys especially when a transmission is in Plain communication. Going a step back, in the phase of tag personalization (when the card is issued to the card holder) the authentication keys are stored on the tag, so the both parties (NFC card and NFC reader) need to have the same key in place. I explain the 3-pass in a very simplified way:

Pre-Step: the reader asks the card to return a value for key xx — this is the begin of the authenticate session.

Step 1: The card generates a random number (“B”) that is encrypted with his key xx and sends it to the reader.

Step 2: the reader receives the random number and decrypts the value with its key xx. Then the reader generates its own random number (“A”), concatenates it with the decrypted random number from the card (“B”), encrypts both and send it to the card (“A || B”).

Step 3: the card receives the encrypted data, decrypts it with key xx and verifies that in the data is his own random number “B” and the random number “A” from the reader. The card generates a session key and sends a “SUCCESS” response to the reader, together with the encrypted number “A”.

At this point the reader can decrypt the number “A” and knows that both parties share the same authentication key and generates a session key, and as both parties do have the same “seed” data for the generation (random numbers “A” and “B”) the will generate the same session key, without exchanging the key itself.

13. Authentication: For some operations on the tag it is necessary run an authentication with the right key first (see above). The sample app allows to authenticate with the default = unchanged keys (e.g. a DES key is of length 8 bytes and is 8 bytes of 0x00, whereas an AES-128 key is of length 16 and is filled with 16 bytes 0f 0x00). For a real application it is necessary to change these default keys to individual keys that need to kept private (not part of this tutorial). For authentication simply click on the “DES” or “AES” button in the row to authenticate:

You may notice that there are two keys looking similar (“M0 Master” and “0 App Master”). The fist key is the Master Application Key for the Master Application (or “root” application) with the AID “000000”. If you need to authenticate on the Master Application you use this key (please keep in mind that on a brand new DESFire EVx card the Master Application Key is of type “DES”, so you need to use the DES-key as well.). The second choice is the Application Master Key (key number 00) that is used for authentications when within an application).

We are following our general path with the next point:

14. Get the Application Key Settings: the command “45: Get KeySettings” returns the information about how many keys (1..13) and of what type (e.g. DES or AES) this application has. The third information is about some settings regarding this application (e.g. the listing files is allowed without an authentication).

15. A very important command is the “F5: Get FileSettings”: it retrieves information about general (e.g. authentication key mapping) and the specific file types (eg. for Record files it returns the actual and maximum number of records). The “permission map” in the example gives for key number 1 a Read & Write Access Right, for key number 2 the Change Access Right, key 3 is the Read Access Key and key number 4 is the Write Access.

16. Before working with a tag we should be sure that the is been able to run our commands and the best way is to ask the tag about this information by communicating the “60: Get Version” command. It returns general tag type (e.g. DESFire), the generation (“EV2”), the tag ize in bytes and some more data.

17. There is a command available that seems to be needless — I’m talking about “51: GetCardUID”. When tapping a tag to the reader the sample app will show the Card UID, but in times of “data privacy and not trackable persons” you could setup your NFC tag to return a random UID at this moment. If you should need to get the “real” and unique card UID you need to run this command — as the response is encrypted you need to run an authentication with any application key first.

18. As the space on a tag is limited to some hundreds of bytes (upto 8K bytes) it is sometimes necessary to check the remaining user space on the tag before creating a new application or file — do this with the “6E: Free Memory” command.

18. As written more then one time, the deletion of a file or application does not release the user space — only a tag formatting using the “FC: FormatPICC” command will release the user memory.

Now it’s getting time to install and run the sample app on your Android device. I’m giving you some “paths” to run the actions with success.

Path 1: Setup your tag with all applications and files

Usually you start with a “brand new” tag that is empty (“factory settings”). Tap the tag at the reader and the UI changes. First we need to create an application; a default AID is already in place (“A1A2A3”), as well the number of keys (fixed, “5”) and lastly choose the key type (default is “AES”) -> press “create the application”. Now select the application and scroll down to the “Work with Standard files” section. The “Standard File” is the only available option, select a File ID (e.g. “0”) and Communication Type (e.g. Default “Plain”). The File Size of “32” is fixed -> press “create the Standard file”.

Path 2: Write to and Read from the Standard File

Tap the tag at the reader, select an existing application, select a file (e.g. “00 Standard File”) and now scroll down to “Authentication with Default Keys”. Authenticate with the “1 App R&W” key by pressing “AES” or “DES” (depending on your “Create Application” setting). Scroll up and enter some data in the edit field above the “write” button, then press “write”. For reading press “read” and scroll up.

Path 3: Write to an Read from the Standard File with wrong authentication keys

This path is similar to path 2 but we are trying intentionally to use the wrong authentications. Tap the tag at the reader, select an existing application, select a file (e.g. “00 Standard File”) and now scroll down to “Authentication with Default Keys”. Authenticate with the “3 App R” key by pressing “AES” or “DES” (depending on your “Create Application” setting). Trying to write to the file will fail, as well authenticating with key “4 App W” followed by reading the file.

Path 4: Additional commands

Tap the tag to the reader, select an existing application, select a file (e.g. “00 Standard File”) and now scroll down to “Work with Standard Files” -> press “file settings” ( shows e.g. the key map). Scroll down to “General Workflow” and press “key settings”, then “tag version” and “free memory”. Scroll up, authenticate with key 0 and press “delete the file”, then again down to “free memory” (note that the space for the Standard File doesn’t get released). Same applies when you are deleting the application. The last command is the read colored button “format” — this will delete all data on the tag and release the user memory.

Just a last note: don’t miss to start the app on your Android device by Android Studio and have a look at the “Logcat” — you find tons of lines showing how the communication is done in both directions.

At this point we are at the end of journey — we are been able to create applications and (Standard) files on a DESFire tag, write to and read from the tag after an authentication and run a lot of service methods.

The full code of the sample app (inclusive a pre-build debug application file in the debug folder, “app-debug.apk”) is available on GitHub using this link: https://github.com/AndroidCrypto/MifareDesfireEv3TutorialNFCjLib

The app is using two external dependencies to work with:

DESFire Tools for Android: https://github.com/skjolber/desfire-tools-for-android

Number Picker: https://github.com/ShawnLin013/NumberPicker

--

--