How to set and unset password on a MIFARE Ultralight EV1 tag?

一笑奈何 提交于 2021-02-04 16:08:22

问题


I would like to be able to set and unset password protection on a MIFARE Ultralight EV1 (MFOUL21) tag using the NfcA? tag technology on Android.

I understand I would use the nfcA.transceive() method for this, but I'm not sure what the arguments to that method would be, so could anyone provide code snippets to set and unset the password?

Update:

With respect to the TapLinx library, I would basically like the nfcA.transceive(...) code snippets equvalent to:

  1. ultralightEV1.programPwd(passwordBytes);
  2. ultralightEV1.programPack(packBytes);
  3. ultralightEV1.enablePasswordProtection(enabled, fromPageNum);
  4. ultralightEV1.authenticatePwd(passwordBytes);

回答1:


Authenticate

ultralightEV1.authenticatePwd(passwordBytes);

In order to authenticate with the password to a MIFARE Ultralight EV1 tag (or NTAG21x), you would need to send the PWD_AUTH (0x1B) command (and possibly verify if the PACK response matches your expectations):

byte[] pass = { (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78 };
byte[] pack = { (byte)0x9A, (byte)0xBC };

byte[] response = nfc.transceive(new byte[] {
    (byte) 0x1B, // PWD_AUTH
    pass[0], pass[1], pass[2], pass[3]
});
if ((response != null) && (response.length >= 2)) {
    // success
    byte[] packReceived = Arrays.copyOf(response, 2);
    if (Arrays.equal(packReceived, pack)) {
        // PACK verified, so tag is authentic (not really, but that whole
        // PWD_AUTH/PACK authentication mechanism was not really meant to
        // bring much security, I hope; same with the NTAG signature btw.)
    }
}

Set password and password-acknowledge

ultralightEV1.programPwd(passwordBytes); ultralightEV1.programPack(packBytes);

For MF0UL11, the password is on page 0x12 and the password-acknowledge (PACK) is on page 0x13 (configuration pages start at 0x10). For MF0UL21, the password is on page 0x27 and the password-acknowledge (PACK) is on page 0x28 (configuration pages start at 0x25).

In order to dynamically find out if your tag is MF0UL11 or MF0UL21, you could send a GET_VERSION (0x60) command:

int cfgOffset = -1;

byte[] response = nfc.transceive(new byte[] {
    (byte) 0x60 // GET_VERSION
});
if ((response != null) && (response.length >= 8)) {
    // success
    if ((response[0] == (byte)0x00) && (response[1] == (byte)0x04)) {
        // tag is from NXP
        if (response[2] == (byte)0x03) {
            // MIFARE Ultralight
            if ((response[4] == (byte)0x01) && (response[5] == (byte)0x00) {
                // MIFARE Ultralight EV1 (V0)
                switch (response[6]) {
                    case (byte)0x0B:
                        // MF0UL11
                        cfgOffset = 0x010;
                        break;
                    case (byte)0x0E:
                        // MF0UL11
                        cfgOffset = 0x025;
                        break;

                    default:
                        // unknown
                        break;
                }
            }
        }
    }
}

Once you found the begin of the configuration pages, you can use a WRITE (0xA2) command to update the values of those pages (assuming you are authenticated with the current password otr the configuration pages are unprotected):

byte[] response = nfc.transceive(new byte[] {
    (byte) 0xA2, // WRITE
    (byte)((cfgOffset + 2) & 0x0FF),    // page address
    pass[0], pass[1], pass[2], pass[3]  // new page data
});
response = nfc.transceive(new byte[] {
    (byte) 0xA2, // WRITE
    (byte)((cfgOffset + 3) & 0x0FF),          // page address
    pack[0], pack[1], (byte)0x00, (byte)0x00  // new page data (always need to write full page)
});

Enable password protection

ultralightEV1.enablePasswordProtection(enabled, fromPageNum);

In order to enable password protection, you need to cofigure the first page that requires the password (AUTH0, byte 3 on page 0x10 for MF0UL11/page 0x25 MF0UL21) and you need to configure the protection mode (PROT, bit 7 of byte 0 on page 0x11 for MF0UL11/page 0x26 MF0UL21).

You would typically first read (READ (0x30) command) the old value of those pages, update the affected bits and bytes, and write the new value to the tag:

int fromPageNum = 4;
boolean enableProtection = true;
boolean enableReadProtection = true;
byte[] response = nfc.transceive(new byte[] {
    (byte) 0x30, // READ
    (byte)(cfgOffset & 0x0FF)  // page address
});
if ((response != null) && (response.length >= 16)) {
    // success
    // NOTE that READ will return *4 pages* starting at page address
    byte auth0 = (byte)0xFF;
    if (enableProtection || enableReadProtection) {
        auth0 = (byte)(fromPageNum & 0x0FF);
    }
    byte[] writeResponse = nfc.transceive(new byte[] {
        (byte) 0xA2, // WRITE
        (byte)((cfgOffset + 0) & 0x0FF),              // page address
        response[0], response[1], response[2], auth0  // new page data
    });
    byte access = (byte)(response[4] & 0x07F);
    if (enableProtection && enableReadProtection) {
        access |= (byte)0x80;
    }
    byte[] writeResponse = nfc.transceive(new byte[] {
        (byte) 0xA2, // WRITE
        (byte)((cfgOffset + 1) & 0x0FF),                // page address
        access, response[5], response[6], response[7],  // new page data
    });
}



回答2:


You can use the TapLinx Library from NXP (available at https://www.mifare.net/en/products/tools/taplinx/) to communicate with MIFARE Ultralight EV1 in an abstracted manner.

To use "transceive", according to the datasheet available at http://www.advanide.com/wp-content/uploads/products/rfid/UltraLight%20EV1_MF0ULX1.pdf the WRITE Command (A2) needs to be used, with addresses 25-28h.

UPDATE: The commands to be sent should be (for MFOUL21):

  1. ultralightEV1.programPwd(passwordBytes); A227AABBCCDD (for Password AABBCCDD)

  2. ultralightEV1.programPack(packBytes); A228EEFF0000 (for PACK 0000)

  3. ultralightEV1.enablePasswordProtection(enabled, fromPageNum); A225xx0000yy (where xx is the modulation mode; 00..strong mod. disabled; 01..strong mod enabled; yy = page where password protection starts)

  4. ultralightEV1.authenticatePwd(passwordBytes); 1BAABBCCDD



来源:https://stackoverflow.com/questions/44395283/how-to-set-and-unset-password-on-a-mifare-ultralight-ev1-tag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!