public byte[] WriteData(byte[] sessionKey, byte fileNo, byte dataIn) { //byte fileNo = 0x01; byte[] offset = new byte[] { 0x00, 0x00, 0x00 }; //offset of 0 byte[] length = new byte[] { 0x00, 0x00, 0x01 }; //length of 1 byte[] dataToWrite = new byte[] { dataIn }; byte[] dataForCRC32Header = new byte[] { (byte)DesfireCommand.CommandType.WriteData, fileNo, offset[2], offset[1], offset[0], length[2], length[1], length[0] }; byte[] dataForCRC32 = new byte[dataForCRC32Header.Length + dataToWrite.Length]; Array.Copy(dataForCRC32Header, dataForCRC32, dataForCRC32Header.Length); Array.Copy(dataToWrite, 0, dataForCRC32, dataForCRC32Header.Length, dataToWrite.Length); uint crc32 = Crc32.Compute(dataForCRC32); string dataPlusCRC = Formatting.ByteArrayToHexString(dataToWrite) + Formatting.ByteArrayToHexString(BitConverter.GetBytes(crc32)); byte[] dataPlusCRCPadded = Formatting.HexStringToByteArray(dataPlusCRC); Formatting.PadToMultipleOf(ref dataPlusCRCPadded, 16); string initialIV = "00000000000000000000000000000000"; byte[] dataPlusCRCResultPaddedEncrypted = AESCrypto.AESEncrypt( sessionKey, Formatting.HexStringToByteArray(initialIV), dataPlusCRCPadded); byte[] extractIV = new byte[16]; Array.Copy(dataPlusCRCResultPaddedEncrypted, dataPlusCRCResultPaddedEncrypted.Length - 16, extractIV, 0, 16); byte[] cmdToSendHeader = new byte[] { fileNo, offset[2], offset[1], offset[0], length[2], length[1], length[0] }; byte[] cmdToSend = new byte[cmdToSendHeader.Length + dataPlusCRCResultPaddedEncrypted.Length]; Array.Copy(cmdToSendHeader, cmdToSend, cmdToSendHeader.Length); Array.Copy(dataPlusCRCResultPaddedEncrypted, 0, cmdToSend, cmdToSendHeader.Length, dataPlusCRCResultPaddedEncrypted.Length); DesfireCommand desfireCommand = new DesfireCommand() { Command = (byte)DesfireCommand.CommandType.WriteData, Data = cmdToSend }; DesfireResponse desfireResFile = SendCommand(desfireCommand) as DesfireResponse; if (!desfireResFile.Succeeded) { throw new DesFireException("Error:" + desfireResFile.SW); } byte[] cmac = AESCMAC.CMAC( sessionKey, extractIV, new byte[] { desfireResFile.SW2 }); byte[] updatedIV = cmac; byte[] data = ReadData(sessionKey, updatedIV, fileNo); if (data[0] != dataToWrite[0]) { throw new DesFireException("Data read not the same as data written"); } return(data); }
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); }