I am developing an NFC test app using Xamarin.Forms and the Plugin.NFC library: https://github.com/franckbour/Plugin.NFC/
However, this library does not include a feature for setting or removing passwords, so I need to add that functionality myself.
I am adding the card information here.
My card is ISO 14443-3A
NXP - NTAG213
NfcA, MifareUltralight, Ndef
and below there is exported memory
and here is the memory dump
[ 04:C1:FE:B3 ] Addr. 00 : UID0 - UID2 / BCC0
[ F2:04:74:80 ] Addr. 01 : UID3 - UDI6
[ 02:48:00:00 ] Addr. 02 : BCC1 / INT. / LOCK0 - LOCK1
[ E1:10:12:00 ] Addr. 03 : OTP0 - OTP3
[ 01:03:A0:0C ] Addr. 04 : DATA
[ 34:03:0A:D1 ] Addr. 05 : DATA
[ 01:06:54:02 ] Addr. 06 : DATA
[ 65:6E:61:61 ] Addr. 07 : DATA
[ 61:FE:00:00 ] Addr. 08 : DATA
[ 63:3F:54:61 ] Addr. 09 : DATA
[ 67:49:64:3D ] Addr. 0A : DATA
[ 30:34:43:31 ] Addr. 0B : DATA
[ 46:45:46:32 ] Addr. 0C : DATA
[ 30:34:37:34 ] Addr. 0D : DATA
[ 38:30:26:50 ] Addr. 0E : DATA
[ 61:79:6C:6F ] Addr. 0F : DATA
[ 61:64:3D:4D ] Addr. 10 : DATA
[ 79:5F:49:6D ] Addr. 11 : DATA
[ 70:6F:72:74 ] Addr. 12 : DATA
[ 61:6E:74:5F ] Addr. 13 : DATA
[ 4B:65:79:FE ] Addr. 14 : DATA
[ 73:20:65:76 ] Addr. 15 : DATA
[ 65:72:79:74 ] Addr. 16 : DATA
[ 68:69:6E:67 ] Addr. 17 : DATA
[ 20:6F:6B:3F ] Addr. 18 : DATA
[ 20:79:65:73 ] Addr. 19 : DATA
[ 20:69:74:20 ] Addr. 1A : DATA
[ 69:73:FE:00 ] Addr. 1B : DATA
[ 70:73:75:6D ] Addr. 1C : DATA
[ 20:68:61:73 ] Addr. 1D : DATA
[ 20:62:65:65 ] Addr. 1E : DATA
[ 6E:20:74:68 ] Addr. 1F : DATA
[ 65:20:69:6E ] Addr. 20 : DATA
[ 64:75:73:74 ] Addr. 21 : DATA
[ 72:79:27:73 ] Addr. 22 : DATA
[ 20:73:74:61 ] Addr. 23 : DATA
[ 6E:64:61:72 ] Addr. 24 : DATA
[ 64:20:64:75 ] Addr. 25 : DATA
[ 6D:6D:79:FE ] Addr. 26 : DATA
[ 00:00:00:00 ] Addr. 27 : DATA
[ 00:00:00:BD ] Addr. 28 : LOCK2 - LOCK4
[ 04:00:00:00 ] Addr. 29 : CFG 0 (MIRROR / AUTH0)
[ 00:05:00:00 ] Addr. 2A : CFG 1 (ACCESS)
[ 00:00:00:00 ] Addr. 2B : PWD0 - PWD3
[ 00:00:00:00 ] Addr. 2C : PACK0 - PACK1
I can detect whether a card is password-protected or not using the following code in Android.
public bool CheckConfiguration()
{
bool passExist;
MifareUltralight mu = null;
try
{
mu = MifareUltralight.Get( _currentTag );
mu.Connect();
var answer = mu.ReadPages( 41 );
byte auth0 = answer[ 3 ];
passExist = auth0 < (byte)0xEB;
Debug.WriteLine( "Page 41 (addr29)" );
Debug.WriteLine( string.Join( "", answer ) );
mu.Close();
}
catch( Exception e )
{
mu?.Close();
passExist = true;
}
return passExist;
}
The authentication status is located at address 0x29. If the last byte is 0x00, it means the card is password-protected; if the last byte is 0xFF, it means the card is not password-protected.
I was able to send a basic command and receive a result successfully.
private void TestReadBlock(MifareUltralight mfu)
{
try
{
if (!mfu.IsConnected)
mfu.Connect();
// Read block 4 as a test
byte[] readCommand = { 0x30, 0x04 }; // Read block 4
byte[] response = mfu.Transceive(readCommand);
if (response != null)
{
Debug.WriteLine($"Read successful. Response: {BitConverter.ToString(response)}");
}
else
{
Debug.WriteLine("Read failed. Response is null.");
}
}
catch (Java.IO.IOException ex)
{
Debug.WriteLine($"IOException during read: {ex.Message}");
}
finally
{
try
{
if (mfu.IsConnected)
mfu.Close();
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to close connection: {ex.Message}");
}
}
}
I can get a result.
However, when I attempt authentication with the 0x1B command, I always receive the error "Tag was lost."
For example, I get an exception when calling the Transceive method the first time.
private bool RemovePasswordProtection(MifareUltralight mfu)
{
try
{
if (!mfu.IsConnected)
mfu.Connect();
byte[] pwdAuthCommand = { 0x1B, 0x00, 0x00, 0x00, 0x00 };
byte[] response = mfu.Transceive(pwdAuthCommand);
byte[] writeCommand = { 0xA2, 0x29, 0xFF, 0x00, 0x00, 0x00 };
mfu.Transceive(writeCommand);
return true;
}
catch (Exception ex)
{
Debug.WriteLine($"Error removing password protection: {ex.Message}");
return false;
}
finally
{
try
{
if (mfu.IsConnected)
mfu.Close();
}
catch { }
}
}
I am not sure if the command is incorrect or if there is another underlying issue. One thing to note is that I call this authentication method after detecting a tag.
EDIT:
It seems that the password is not in the memory dump. When I set a password and then remove it, there is only on difference as follow
EDIT 2:
I add my password to the auth command however I get always the "Tag was lost" exception while executing mfu.Transceive( pwdAuthCommand );
private async Task<bool> TryRawAuthentication( MifareUltralight mfu )
{
try
{
if( !mfu.IsConnected )
mfu.Connect();
byte[] pwdAuthCommand = {
0x1B, // PWD_AUTH command
0x31, // '1'
0x32, // '2'
0x33, // '3'
0x34 // '4'
};
Debug.WriteLine( $"Sending PWD_AUTH command: {BitConverter.ToString( pwdAuthCommand )}" );
byte[] response = mfu.Transceive( pwdAuthCommand );
Debug.WriteLine( $"NfcA Auth Response: {BitConverter.ToString( response )}" );
return true;
}
catch( Exception ex )
{
Debug.WriteLine( $"Raw authentication error: {ex.Message}" );
return false;
}
}