Exemple #1
0
        public void CreateFile(byte fileNo)
        {
            //create a std data file
            //byte fileNo = 0x01;
            byte         commSettings = (byte)CommunicationSettings.FullEnciphered;
            AccessRights accessRights = new AccessRights()
            {
                ChangeAccess    = 0x00, //use application master key for all access
                ReadWriteAccess = 0x00, //use application master key for all access
                WriteAccess     = 0x00, //use application master key for all access
                ReadAccess      = 0x00  //use application master key for all access
            };

            byte[] accessRightsBytes = accessRights.getValue();
            byte[] fileSize          = new byte[] { 0x00, 0x00, 0x20 }; //32 bytes in size
            byte[] dataFile          = new byte[] { fileNo, commSettings, accessRightsBytes[1], accessRightsBytes[0], fileSize[2], fileSize[1], fileSize[0] };

            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.CreateStdDataFile,
                Data    = dataFile
            };
            DesfireResponse desfireResFile = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireResFile.Succeeded)
            {
                throw new DesFireException("Error:" + desfireResFile.SW);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        public void GetKeySettings()
        {
            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.GetKeySettings
            };
            DesfireResponse desfireResFile = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireResFile.Succeeded)
            {
                throw new DesFireException("Error:" + desfireResFile.SW);
            }
        }
Exemple #5
0
        public void GetKeyVersion(byte keyNo)
        {
            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.GetKeyVersion,
                Data    = new byte[] { keyNo }
            };
            DesfireResponse desfireResFile = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireResFile.Succeeded)
            {
                throw new DesFireException("Error:" + desfireResFile.SW);
            }
        }
Exemple #6
0
        public void SelectApplication(byte[] aid)
        {
            if (aid.Length != 3)
            {
                throw new NotSupportedException();
            }

            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.SelectApplication,
                Data    = aid.Reverse().ToArray() //little endian
            };
            DesfireResponse desfireRes = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireRes.Succeeded)
            {
                throw new Exception("Failure selecting application, SW=" + desfireRes.SW + " (" + desfireRes.SWTranslation + ")");
            }
        }
Exemple #7
0
        public void CreateApplication(byte[] aid)
        {
            AppMasterKeySettings apks = new AppMasterKeySettings()
            {
                Bit0_AllowChangeMasterKey = true,
                Bit1_FreeDirectoryListAccessWithoutMasterKey = true, //TODO: chnge to false
                Bit2_FreeCreateDeleteFileWithoutMasterKey    = true, //TODO: chnge to false
                Bit3_ConfigurationChangeable = true
            };
            ChangeKeyAccessRights ckar = new ChangeKeyAccessRights()
            {
                ChangeKeyAccessRightsType = ChangeKeyAccessRightsEnum.ApplicationMasterKeyAuthenticationIsNecessaryToChangeAnyKey
            };

            apks.Bit4_Bit7_ChangeKeyAccessRights = ckar;

            CreateApplicationKeySettings2 caks2 = new CreateApplicationKeySettings2()
            {
                NumberOfKeysThatCanbeStoredinApplicationForCryptographicPurposes = 1,
                TwoByteFileIdentifiersSupported = false,
                CryptoMethod = CryptoMethodEnum.Crypto_AES
            };
            //byte[] aid = new byte[] {0x00, 0x00, 0x01 };//3 byte aid MSB : LSB
            byte keyset1 = apks.getValue();
            byte keyset2 = caks2.getValue();

            byte[] data = new byte[] { aid[2], aid[1], aid[0], keyset1, keyset2 };

            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.CreateApplication,
                Data    = data
            };
            DesfireResponse desfireRes = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireRes.Succeeded)
            {
                throw new DesFireException("Error:" + desfireRes.SW);
            }
        }
Exemple #8
0
        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));
        }
Exemple #9
0
        public CardDetails ReadCardDetails()
        {
            DesfireCommand desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.GetVersion,
                Data    = null
            };
            DesfireResponse desfireRes = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireRes.SubsequentFrame || desfireRes.ResponseData.Length != 7)
            {
                return(null);
            }

            CardDetails card = new CardDetails()
            {
                HardwareVendorID     = desfireRes.ResponseData[0],
                HardwareType         = desfireRes.ResponseData[1],
                HardwareSubType      = desfireRes.ResponseData[2],
                HardwareMajorVersion = desfireRes.ResponseData[3],
                HardwareMinorVersion = desfireRes.ResponseData[4],
                HardwareStorageSize  = desfireRes.ResponseData[5],
                HardwareProtocolType = desfireRes.ResponseData[6]
            };

            desfireCommand = new DesfireCommand()
            {
                Command = (byte)DesfireCommand.CommandType.GetAdditionalFrame
            };
            desfireRes = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireRes.SubsequentFrame || desfireRes.ResponseData.Length != 7)
            {
                // Not expected
                return(null);
            }
            card.SoftwareVendorID     = desfireRes.ResponseData[0];
            card.SoftwareType         = desfireRes.ResponseData[1];
            card.SoftwareSubType      = desfireRes.ResponseData[2];
            card.SoftwareMajorVersion = desfireRes.ResponseData[3];
            card.SoftwareMinorVersion = desfireRes.ResponseData[4];
            card.SoftwareStorageSize  = desfireRes.ResponseData[5];
            card.SoftwareProtocolType = desfireRes.ResponseData[6];

            desfireRes = SendCommand(desfireCommand) as DesfireResponse;

            if (!desfireRes.Succeeded || desfireRes.ResponseData.Length != 14)
            {
                // Not expected
                return(null);
            }

            card.UID = new byte[7];
            System.Buffer.BlockCopy(desfireRes.ResponseData, 0, card.UID, 0, 7);

            card.ProductionBatchNumber = new byte[5];
            System.Buffer.BlockCopy(desfireRes.ResponseData, 7, card.ProductionBatchNumber, 0, 5);

            card.WeekOfProduction = desfireRes.ResponseData[12];
            card.YearOfProduction = desfireRes.ResponseData[13];

            return(card);
        }