Topic: DESfire authentication

Hello,

Has anybody succeeded in authenticating to a DESfire card, then reading/writing data?

I don't know/understand the specifics of DES enough to implement it, from reading publicly available info (i.e http://ridrix.wordpress.com/2009/09/19/ … n-example/ ), my attempts to implement it using the OpenSSL libs haven't gotten far (get 0xAE response) Its probably due to the wrong DES mode or XORing the wrong data.

I don't want to sign an NDA with NXP to get hold of the potentially valuable DESfire Hints doc either.

If someone can post/contribute a working authentication function I'd be willing to return the favour.. i.e write desfire functions for libfreefare smile

Re: DESfire authentication

Hi!

mcbridematt wrote:

Has anybody succeeded in authenticating to a DESfire card, then reading/writing data?

Yup smile

I am working on the Mifare DESFire support in libfreefare and authentication is one of the only function done so far.

mcbridematt wrote:

I don't know/understand the specifics of DES enough to implement it, from reading publicly available info (i.e http://ridrix.wordpress.com/2009/09/19/ … n-example/ ), my attempts to implement it using the OpenSSL libs haven't gotten far (get 0xAE response) Its probably due to the wrong DES mode or XORing the wrong data.

This page provides interesting information I used to achieve authentication.  The fact that NXP teaks well-known algorithms to turn them into some weird nxp-specific ones is a PITA...

mcbridematt wrote:

I don't want to sign an NDA with NXP to get hold of the potentially valuable DESfire Hints doc either.

There are copies of the document available on the Internet... (I got mine from http://www.pudn.com/downloads165/ebook/ … 53406.html and can send it to you (I am not under the terms of the NDA) if you don't speak chineese (well, you don't have to BTW wink ))

mcbridematt wrote:

If someone can post/contribute a working authentication function I'd be willing to return the favour.. i.e write desfire functions for libfreefare smile

The code currently in my local copy of the repo only handles DES encryption but I guess that supporting 3DES should not be a big deal of work.  However, before testing it, implementing support for all Mifare DESFire functions is a requirement. This week is scheduled to be a hack week on libfreefare's Mifare DESFire support for me, I hope things will go well.

If you want to play with this, here is a copy-paste of the *development* code related to Mifare DESFire authentication I am using:

#define DESFIRE_TRANSCEIVE(tag, msg, msg_len, res, res_len) \
    do { \
        if (!(nfc_initiator_transceive_dep_bytes (tag->device, msg, msg_len, res, &res_len))) \
            return errno = EIO, -1; \
        if ((1 == res_len) && (OPERATION_OK != res[0])) \
            return MIFARE_DESFIRE(tag)->last_picc_error = res[0], -1; \
    } while (0)

static void
xor8 (uint8_t *ivect, uint8_t *data)
{
    for (int i = 0; i < 8; i++) {
        data[i] ^= ivect[i];
    }   
}

void
rol8(uint8_t *data)
{
    uint8_t first = data[0];
    for (int i = 0; i < 7; i++) {
        data[i] = data[i+1];
    }   
    data[7] = first;
}

void
mifare_cbc_des (uint8_t *key, uint8_t *data, uint8_t *ivect, MifareDirection direction)
{
    /*  
     * FIXME Should we change the way errors traverse this function?
     */
    uint8_t ovect[8];

    if (direction == MD_SEND) {
        xor8 (ivect, data);
    } else {
        memcpy (ovect, data, 8); 
    }   

    DES_key_schedule ks; 
    DES_set_key ((DES_cblock *)key, &ks);

    uint8_t edata[8];
    DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &ks, DES_DECRYPT);
//    stat = ecb_crypt (key, data, 8, DES_HW | DES_DECRYPT);
//
    memcpy (data, edata, 8); 

    if (direction == MD_SEND) {
        memcpy (ivect, data, 8); 
    } else {
        xor8 (ivect, data);
        memcpy (ivect, ovect, 8);
    }
}

int
mifare_desfire_authenticate (MifareTag tag, uint8_t key_no)
{
    ASSERT_ACTIVE (tag);
    ASSERT_MIFARE_DESFIRE (tag);

    MIFARE_DESFIRE(tag)->last_picc_error = OPERATION_OK;

    uint8_t key[8];
    memset (key, '\0', sizeof (key));

#if 0
    /*
     * Parity bits of DES keys are used for key versionning.
     */
    DES_set_odd_parity ((DES_cblock *)&key);
#endif

    uint8_t ivec[8];
    memset (ivec, '\0', sizeof (ivec));

    hexdump (key, 8, "key                   ", 0);
    hexdump (ivec, 8, "ivec                  ", 0);

    uint8_t command[2];
    command[0] = 0x0A;
    command[1] = key_no;

    uint8_t status[9];
    size_t n;
#if 0
    hexdump (command, sizeof (command), "<---                  ", 0);
    if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), status, &n))) {
        tag->active = false; /* Tag is no more active if authentication failed. */
        errno = EIO;
        return -1;
    }

    if (n == 1) {
        tag->last_picc_error = status[0];
        return -1;
    }

    hexdump (status, n, "--->                  ", 0);
#endif
    DESFIRE_TRANSCEIVE (tag, command, sizeof (command), status, n);
    uint8_t PICC_E_RndB[8];
    memcpy (PICC_E_RndB, status+1, 8);
    hexdump (PICC_E_RndB, sizeof (PICC_E_RndB), "e(PICC_RndB)          ", 0);

    uint8_t PICC_RndB[8];
    memcpy (PICC_RndB, PICC_E_RndB, 8);
    mifare_cbc_des (key, PICC_RndB, ivec, MD_RECEIVE);
    hexdump (PICC_RndB, sizeof (PICC_RndB), "  PICC_RndB           ", 0);

    uint8_t PCD_RndA[8];
    DES_random_key ((DES_cblock*)&PCD_RndA);
    hexdump (PCD_RndA, sizeof (PCD_RndA), "  PCD_RndA            ", 0);

    uint8_t PCD_r_RndB[8];
    memcpy (PCD_r_RndB, PICC_RndB, 8);
    rol8 (PCD_r_RndB);

    uint8_t token[16];
    memcpy (token, PCD_RndA, 8);
    memcpy (token+8, PCD_r_RndB, 8);

    hexdump (token, sizeof (token), "  PCD_RndA+PCD_RndB'  ", 0);

    memset (ivec, '\0', sizeof (ivec));
    mifare_cbc_des (key, token, ivec, MD_SEND);
    mifare_cbc_des (key, token+8, ivec, MD_SEND);

    hexdump (token, sizeof (token), "d(PCD_RndA+PCD_RndB') ", 0);

    uint8_t msg[17];
    msg[0] = 0xAF;
    memcpy (msg + 1, token, 16);
    DESFIRE_TRANSCEIVE (tag, msg, sizeof (msg), status, n);

    uint8_t PICC_E_RndA_s[8];
    memcpy (PICC_E_RndA_s, status+1, 8);
    hexdump (PICC_E_RndA_s, sizeof (PICC_E_RndA_s), "e(PICC_RndA')         ", 0);

    uint8_t PICC_RndA_s[8];
    memcpy (PICC_RndA_s, PICC_E_RndA_s, 8);
    memset (ivec, '\0', sizeof (ivec));
    mifare_cbc_des (key, PICC_RndA_s, ivec, MD_RECEIVE);
    hexdump (PICC_RndA_s, sizeof (PICC_RndA_s), "  PICC_RndA'          ", 0);

    uint8_t PCD_RndA_s[8];
    memcpy (PCD_RndA_s, PCD_RndA, 8);
    rol8 (PCD_RndA_s);
    hexdump (PCD_RndA_s, sizeof (PCD_RndA_s), "  PCD_RndA'           ", 0);


    if (0 != memcmp (PCD_RndA_s, PICC_RndA_s, 8)) {
        return -1;
    }

    return 0;
}

Re: DESfire authentication

You've made my day!. I'll try it out and send some feedback

Re: DESfire authentication

It works!

On a blank desfire card I was able to create an application, some files and r/w data to the files.

Here is my demo app, it opens application 1 and writes to file 3 the current time.
http://pastebin.com/FbCJfDbU
I based it off my MF Classic demo so there is some stray mfc code, but at least we have something!

Sample output: http://pastebin.com/UtQQZ1xN

I even poked around a public transport card (myki) with it, didn't find anything interesting that wasn't encrypted though.

Re: DESfire authentication

mcbridematt wrote:

It works!

Cool!

I am working only on authentication management functions right now (Authenticate, ChangeKey, ChangeKeySettings, GetKeySettings, GetKeyVersion) so if you want to poke around and contribute some functions, I can create a branch where to push my ongoing changes so that you could easily add them wink  You would just have to keep in mind that the library is licensed under the LGPL and that unit tests are expected with any feature add/change (we use cutter which is realy cool but not packaged in may distros).

Just tell me if you would be interested in hacking in libfreefare.

Re: DESfire authentication

romain wrote:

I can create a branch where to push my ongoing changes so that you could easily add them wink

Please do, I would join in quickly. I've implemented most of DESFire functions and intent to contribute back. Unfortunately, it strongly ties to our specific application and does not use libnfc directly. So I'd rather help re-implement a cleaner version.

You would just have to keep in mind that the library is licensed under the LGPL and that unit tests are expected with any feature add/change (we use cutter which is realy cool but not packaged in may distros).

Just tell me if you would be interested in hacking in libfreefare.

You may want to consider libgcrypt for cryptography functions. Unlike openssl, libgcrypt is also LGPL. I used openssl first but then move to libgcrypt.

Re: DESfire authentication

Hey

I just pushed the development code to the freefare-desfire branch:

svn co http://nfc-tools.googlecode.com/svn/branches/libfreefare-desfire/

Some notes in the README file might be useful.  You may want to download and install cutter before running autoreconf so that it will be detected and usable.

Last note: refrain from running the DESFire tests without first checking what they do: I use the test that creates application to actually remove applications (sic)... This will change as soon as the mifare_desfire_change_key works but for now it's a lnown behaviour.

Happy hacking!

Romain

Re: DESfire authentication

I'd be interested in writing some functionality but I need to get up to speed with libfreefare and cutter first. Also, my C skills aren't that appealing tongue

I also need to get it running on my main platform, OS X, I've already submitted issue #21 to fix configure
There is a stray reference to rpc/des_crypt.h which you can remove as well (doesn't exist on OS X)

Re: DESfire authentication

I've got a rudimentary file implementation - create/delete/list and soon read/write coming, yes, including cutter tests smile

Re: DESfire authentication

FYI, libfreefare's Mifare DESFire support is considered complete:
http://www.libnfc.org/community/topic/1 … bfreefare/