public byte[] ReadData(byte[] sessionKey, byte[] updatedIV, byte fileNo) { byte[] offset = new byte[] { 0x00, 0x00, 0x00 }; //offset of 0 byte[] length = new byte[] { 0x00, 0x00, 0x01 }; //length of 1 byte[] dataForCMAC = new byte[] { (byte)DesfireCommand.CommandType.ReadData, fileNo, offset[2], offset[1], offset[0], length[2], length[1], length[0] }; byte[] cmac = AESCMAC.CMAC( sessionKey, updatedIV, dataForCMAC); updatedIV = cmac; byte[] cmdToSend = new byte[] { fileNo, offset[2], offset[1], offset[0], length[2], length[1], length[0] }; DesfireCommand desfireCommand = new DesfireCommand() { Command = (byte)DesfireCommand.CommandType.ReadData, Data = cmdToSend }; DesfireResponse desfireRes = SendCommand(desfireCommand) as DesfireResponse; if (!desfireRes.Succeeded) { throw new DesFireException("Error:" + desfireRes.SW); } byte[] dataBytes = AESCrypto.AESDecrypt( sessionKey, updatedIV, desfireRes.ResponseData); byte[] extractIV = new byte[16]; Array.Copy(desfireRes.ResponseData, desfireRes.ResponseData.Length - 16, extractIV, 0, 16); int lengthofData = 0x01; byte[] data = new byte[lengthofData]; Array.Copy(dataBytes, data, data.Length); byte[] crc = new byte[4]; Array.Copy(dataBytes, data.Length, crc, 0, crc.Length); //crc is 4 bytes long byte[] dataPlusStatus = new byte[data.Length + 1]; Array.Copy(data, dataPlusStatus, data.Length); Array.Copy(new byte[] { 0x00 }, 0, dataPlusStatus, data.Length, 1); uint crc32 = Crc32.Compute(dataPlusStatus); //compare crc32 to crc if (BitConverter.ToUInt32(crc, 0) != crc32) { throw new DesFireException("CRC32 error"); } return(data); }
public byte[] AuthenticateAES() { string initialIV = "00000000000000000000000000000000"; string key = "00000000000000000000000000000000"; DesfireCommand desfireCommand = new DesfireCommand() { Command = (byte)DesfireCommand.CommandType.AuthenticateAES, Data = new byte[] { 0x00 } //1 byte key number }; DesfireResponse desfireRes1 = SendCommand(desfireCommand) as DesfireResponse; if (!desfireRes1.SubsequentFrame) //additional frames expected { throw new DesFireException("Error:" + desfireRes1.SW); } byte[] rndBBytes = AESCrypto.AESDecrypt( Formatting.HexStringToByteArray(key), Formatting.HexStringToByteArray(initialIV), desfireRes1.ResponseData); byte[] rndBRotatedBytes = Formatting.RotateRight(rndBBytes); string rndAGenerated = "2347C1557F80707ABDFF86BF9D965CA7"; string rndAPlusRndBRotated = rndAGenerated + Formatting.ByteArrayToHexString(rndBRotatedBytes); string ivNew = Formatting.ByteArrayToHexString(desfireRes1.ResponseData); byte[] rndAPlusRndBRotatedCipherBytes = AESCrypto.AESEncrypt( Formatting.HexStringToByteArray(key), Formatting.HexStringToByteArray(ivNew), Formatting.HexStringToByteArray(rndAPlusRndBRotated)); desfireCommand = new DesfireCommand() { Command = (byte)DesfireCommand.CommandType.GetAdditionalFrame, Data = rndAPlusRndBRotatedCipherBytes //32 byte enciphered RndA/RndB }; byte[] extractIV = new byte[16]; Array.Copy(rndAPlusRndBRotatedCipherBytes, rndAPlusRndBRotatedCipherBytes.Length - 16, extractIV, 0, 16); DesfireResponse desfireRes2 = SendCommand(desfireCommand) as DesfireResponse; if (!desfireRes2.Succeeded) { throw new DesFireException("Error:" + desfireRes2.SW); } byte[] rndARotatedBytes = AESCrypto.AESDecrypt( Formatting.HexStringToByteArray(key), extractIV, desfireRes2.ResponseData); byte[] rndABytes = Formatting.RotateLeft(rndARotatedBytes); if (rndAGenerated != Formatting.ByteArrayToHexString(rndABytes)) { throw new DesFireException("rndA generated not same as rndA received"); } string rndAString = Formatting.ByteArrayToHexString(rndABytes); string rndBString = Formatting.ByteArrayToHexString(rndBBytes); string sessionKey = rndAString.Substring(0, 8) + rndBString.Substring(0, 8) + rndAString.Substring(24, 8) + rndBString.Substring(24, 8); return(Formatting.HexStringToByteArray(sessionKey)); }