nfc-tools / libfreefare

A convenience API for NFC cards manipulations on top of libnfc.
Other
387 stars 106 forks source link

INTEGRITY_ERROR when changing application key from DES to AES #67

Closed davidhuwyler closed 7 years ago

davidhuwyler commented 7 years ago

As far as i understand it, the INTEGRITY_ERROR is either a CRC or a padding Bytes issue.

Code which result in the error:

#if defined(HAVE_CONFIG_H)
    #include "config.h"
#endif

#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <nfc/nfc.h>

#include <freefare.h>

uint8_t masterKey_data[16]      = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

uint8_t oldAppKey_data[8]   =     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t newAppKey_data[16]  =     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

uint32_t appID_data             = 0x112233;

#define MASTER_KEY_VERSION 0x00
#define APP_KEY_VERSION 0x00

struct {
    bool interactive;
} configure_options = {
    .interactive = true
};

static 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 *device = NULL;
    FreefareTag *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);
    }
    }
    // Remaining args, if any, are in argv[optind .. (argc-1)]

    nfc_connstring devices[8];
    size_t device_count;

    nfc_context *context;
    nfc_init(&context);
    if (context == NULL)
    errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");

    device_count = nfc_list_devices(context, devices, 8);
    if (device_count <= 0)
    errx(EXIT_FAILURE, "No NFC device found.");

    for (size_t d = 0; (!error) && (d < device_count); d++) {
    device = nfc_open(context, devices[d]);
    if (!device) {
        warnx("nfc_open() failed.");
        error = EXIT_FAILURE;
        continue;
    }

    tags = freefare_get_tags(device);
    if (!tags) {
        nfc_close(device);
        errx(EXIT_FAILURE, "Error listing Mifare DESFire tags.");
    }

    for (int i = 0; (!error) && tags[i]; i++) {
        if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
        continue;

        char *tag_uid = freefare_get_tag_uid(tags[i]);
        char buffer[BUFSIZ];

        int res;

        res = mifare_desfire_connect(tags[i]);
        if (res < 0) {
        warnx("Can't connect to Mifare DESFire target.");
        error = EXIT_FAILURE;
        break;
        }

        // Make sure we've at least an EV1 version
        struct mifare_desfire_version_info info;
        res = mifare_desfire_get_version(tags[i], &info);
        if (res < 0) {
        freefare_perror(tags[i], "mifare_desfire_get_version");
        error = 1;
        break;
        }
        if (info.software.version_major < 1) {
        warnx("Found old DESFire, skipping");
        continue;
        }

        printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
        bool do_it = true;

        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) {

        printf("1. Authenticate with Master key...\n");
        MifareDESFireKey default_key = mifare_desfire_aes_key_new(masterKey_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 oldAppKey = mifare_desfire_des_key_new_with_version(oldAppKey_data);
        MifareDESFireKey newAppKey = mifare_desfire_aes_key_new(newAppKey_data);

        printf("Set app key as default key...\n");
        mifare_desfire_key_set_version(oldAppKey, APP_KEY_VERSION);
        res = mifare_desfire_set_default_key(tags[i], oldAppKey);
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_set_default_key");
            error = EXIT_FAILURE;
            break;
        }

        printf("Create application...\n");  
        MifareDESFireAID aid = mifare_desfire_aid_new(appID_data);  
        res = mifare_desfire_create_application(tags[i], aid, 0x0F, 1);  
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_create_application");
            error = EXIT_FAILURE;
            break;
        }

        printf("Select application...\n");  
        res = mifare_desfire_select_application(tags[i], aid);
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_select_application");
            error = EXIT_FAILURE;
            break;
        }       

        printf("Authenticate with old app key...\n");       
        res = mifare_desfire_authenticate(tags[i], 0, oldAppKey);
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_authenticate");
            error = EXIT_FAILURE;
            break;
        }   

        printf("Change APP Key settings...\n"); 
        res = mifare_desfire_change_key_settings(tags[i], 0x0F);
        if (res < 0)
        {
              errx(EXIT_FAILURE, "ChangeKeySettings failed");
        }

        printf("Change App master Key DES to AES...\n");    
        mifare_desfire_key_set_version(newAppKey, APP_KEY_VERSION);     
        res = mifare_desfire_change_key(tags[i], 0, newAppKey, oldAppKey);
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_change_key");
            error = EXIT_FAILURE;
            break;
        }

        printf("Authenticate with New app key...\n");       
        res = mifare_desfire_authenticate(tags[i], 0, newAppKey);
        if (res < 0) {
            freefare_perror(tags[i], "mifare_desfire_authenticate");
            error = EXIT_FAILURE;
            break;
        }       

        mifare_desfire_key_free(oldAppKey);
        mifare_desfire_key_free(newAppKey);

        }

        mifare_desfire_disconnect(tags[i]);
        free(tag_uid);
    }

    freefare_free_tags(tags);
    nfc_close(device);
    }
    nfc_exit(context);
    exit(error);
}

Console Output:

1. Authenticate with Master key...
Set app key as default key...
Create application...
Select application...
Authenticate with old app key...
Change APP Key settings...
Change App master Key DES to AES...
mifare_desfire_change_key: INTEGRITY_ERROR

So I think there is a library problem

I am useing the PN7120 with jgeslin/libnfc Lib.

davidhuwyler commented 7 years ago

Closed because it was a user problem not a library issue :-)

hurricanefrog commented 1 year ago

Closed because it was a user problem not a library issue :-)

Uhm? What did you do? I also have an integrity error (0x1E) changing the PICC key from DES to AES with mifare_desfire_change_key

hurricanefrog commented 1 year ago

I even get the error when changing from DES key to DES key.

However, with a DESfire card with a AES PICC key, I can change the key without getting an 0x1E / integrity error.

hurricanefrog commented 1 year ago

Problem might be DES related? I can't even issue a mifare_desfire_get_card_uid_raw, it results in CRC not verified in decyphered stream. So it's somehow crypto related it seems

hurricanefrog commented 1 year ago

Nevermind. I have to use mifare_desfire_des_key_new instead of mifare_desfire_3des_key_new for the default PICC key of all zeroes.