borepin/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs
2020-10-14 00:26:23 +02:00

710 lines
19 KiB
C#

using NFC;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire;
using NFC.NXP_MIFARE_DESFire.Exceptions;
using NSubstitute;
using NUnit.Framework;
using System;
namespace NFC_Test.NXP_MIFARE_DESFire
{
[TestFixture]
public class MIFARE_DESFire_Test
{
#region Helper Methods
[Test]
public void GenerateDefaultKey()
{
uint i = 16;
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.GenerateEmptyKey(i);
for(int e = 0; e < i; e++)
{
if(data[e] != 0x00)
{
Assert.Fail("Data is not 0x00");
}
}
}
[Test]
public void CheckAPDUResponse__NULL()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
desfire.CheckAPDUResponse(null);
});
}
[Test]
public void CheckAPDUResponse__UNKNOWN()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x00,
SW2 = 0x00
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<Exception>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__OPERATION_OK()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
[Test]
public void CheckAPDUResponse__NO_CHANGES()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x0C
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
[Test]
public void CheckAPDUResponse__ILLEGAL_COMMAND_CODE()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x1C
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<IllegalCommandCodeException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__INTEGRITY_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x1E
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<IntegrityErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__NO_SUCH_KEY()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x40
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<NoSuchKeyException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__LENGTH_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x7E
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<LengthErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__PERMISSION_DENIED()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x9D
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<PermissionDeniedException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__PARAMETER_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x9E
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ParameterErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__AUTHENTICATION_DELAY()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAD
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<AuthenticationDelayException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__AUTHENTICATION_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAE
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<AuthenticationErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__ADDITIONAL_FRAME()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAF
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
[Test]
public void CheckAPDUResponse__BOUNDARY_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xBE
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<BoundaryErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__COMMAND_ABORTED()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xCA
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<CommandAbortedException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__DUPLICATE_ERROR()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xDE
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<DuplicateErrorException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
[Test]
public void CheckAPDUResponse__FILE_NOT_FOUND()
{
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xF0
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<FileNotFoundException>(
delegate
{
desfire.CheckAPDUResponse(response);
});
}
#endregion
#region Crypto Operation
[Test]
public void ExtractLastBlock()
{
byte[] data = new byte[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
byte[] expected_lastblock = new byte[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] lastblock = desfire.ExtractLastBlock(data, 8);
Assert.AreEqual(expected_lastblock, lastblock);
}
[Test]
public void ExtractLastBlock_WrongBlocksize()
{
byte[] data = new byte[]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentException>(
delegate
{
byte[] lastblock = desfire.ExtractLastBlock(data, 7);
});
}
[Test]
public void ExtractLastBlock_Null()
{
byte[] data = null;
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
byte[] lastblock = desfire.ExtractLastBlock(data, 7);
});
}
[Test]
public void RotateLeft()
{
byte[] data = new byte[]
{
0x01, 0x02, 0x03, 0x04
};
byte[] expected_data_left = new byte[]
{
0x02, 0x03, 0x04, 0x01
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateLeft(data);
Assert.AreEqual(expected_data_left, data_left);
}
[Test]
public void RotateLeft_Null()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
byte[] lastblock = desfire.RotateLeft(null);
});
}
[Test]
public void RotateRight()
{
byte[] data = new byte[]
{
0x01, 0x02, 0x03, 0x04
};
byte[] expected_data_left = new byte[]
{
0x04, 0x01, 0x02, 0x03
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateRight(data);
Assert.AreEqual(expected_data_left, data_left);
}
[Test]
public void RotateRight_Null()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
byte[] lastblock = desfire.RotateRight(null);
});
}
[Test]
public void Concatenate()
{
byte[] data_a = new byte[]
{
0x01, 0x02, 0x03, 0x04
};
byte[] data_b = new byte[]
{
0x05, 0x06, 0x07, 0x08
};
byte[] expected_data_c = new byte[]
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.Concatenate(data_a, data_b);
Assert.AreEqual(expected_data_c, data_c);
}
[Test]
public void Concatenate_ABC()
{
byte[] data_a = new byte[]
{
0x01, 0x02, 0x03, 0x04
};
byte[] data_b = new byte[]
{
0x05, 0x06, 0x07, 0x08
};
byte[] data_c = new byte[]
{
0x09, 0xA0, 0xB0, 0xC0
};
byte[] expected_data_d = new byte[]
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xB0, 0xC0
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_d = desfire.Concatenate(data_a, data_b, data_c);
Assert.AreEqual(expected_data_d, data_d);
}
[Test]
public void Concatenate_Null()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
byte[] lastblock = desfire.Concatenate(null, null);
});
}
[Test]
public void XOR()
{
byte[] data_a = new byte[]
{
0x00, 0xF0, 0x00, 0xF0
};
byte[] data_b = new byte[]
{
0x0F, 0x00, 0x0F, 0x00
};
byte[] expected_data_c = new byte[]
{
0x0F, 0xF0, 0x0F, 0xF0
};
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.XOR(data_a, data_b);
Assert.AreEqual(expected_data_c, data_c);
}
[Test]
public void XOR_null()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentNullException>(
delegate
{
byte[] lastblock = desfire.XOR(null, null);
});
}
[Test]
public void GenerateSessionKey_AES()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91");
Console.WriteLine(desfire.ConvertToHexString(rndA));
byte[] rndB = desfire.ConvertFromHexString("482ddc54426e6dee560413b8d95471f5");
Console.WriteLine(desfire.ConvertToHexString(rndB));
byte[] expected_sessionkey = desfire.ConvertFromHexString("bc14dfde482ddc54f06fdd91d95471f5");
Console.WriteLine(desfire.ConvertToHexString(expected_sessionkey));
byte[] sessionkey = desfire.GenerateSesionKey_AES(rndA, rndB);
Console.WriteLine(desfire.ConvertToHexString(sessionkey));
Assert.AreEqual(expected_sessionkey, sessionkey);
}
#endregion
#region DESFire Commands
[Test]
public void AuthenticateISO_DES()
{
ICard card = Substitute.For<ICard>();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAF,
Body = HexConverter.ConvertFromHexString("5D994CE085F24089")
};
APDUResponse response_challenge_response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00,
Body = HexConverter.ConvertFromHexString("913C6DED84221C41")
};
byte[] rndA = HexConverter.ConvertFromHexString("849B36C5F8BF4A09");
byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0x1A)).Returns(response_challenge_request);
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_DES(0x00, key, rndA);
byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759");
byte[] expected_iv = desfire.GenerateEmptyKey(8);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
Assert.AreEqual(expected_iv, desfire._IV);
}
[Test]
public void AuthenticateISO_AES()
{
ICard card = Substitute.For<ICard>();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAF,
Body = HexConverter.ConvertFromHexString("43a28e28c653df83cd85039714bccb51")
};
APDUResponse response_challenge_response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00,
Body = HexConverter.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f")
};
byte[] rndA = HexConverter.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1");
byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAA)).Returns(response_challenge_request);
card.Transmit(Arg.Is<APDUCommand>(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_AES(0x00, key, rndA);
byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703");
byte[] expected_iv = desfire.GenerateEmptyKey(16);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
Assert.AreEqual(expected_iv, desfire._IV);
}
[Test]
public void ChangeKey_AES()
{
ICard card = Substitute.For<ICard>();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00
};
byte[] new_key = HexConverter.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530");
byte[] sessionkey = HexConverter.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3");
byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey;
desfire._IV = iv;
card.Transmit(null).ReturnsForAnyArgs(response);
desfire.ChangeKey_AES(0x00, new_key, 0x10);
}
[Test]
public void ChangeOtherKey_AES()
{
ICard card = Substitute.For<ICard>();
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00
};
byte[] new_key = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12");
byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
byte[] sessionkey = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");
byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey;
desfire._IV = iv;
card.Transmit(null).ReturnsForAnyArgs(response);
desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10);
}
#endregion
#region Configuration Generator
[Test]
public void GenerateFileAccessRights()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04));
}
[Test]
public void GenerateFileAccessRights_OutOfRange()
{
MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws<ArgumentOutOfRangeException>(
delegate
{
desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00);
});
}
#endregion
}
}