Exemple #1
0
        /// <summary>
        /// Before you can exchange data with a MiFare chip, the transponder has to be activated (or
        /// „selected“ in the ISO14443 language). Card will be in active state after this call.
        /// Note that something isn't right about the SAK byte, it appears to be hardcoded to 9 from
        /// the reader and *not* coming from the card being communicated with!
        /// </summary>
        /// <returns>
        /// The mifare select.
        /// </returns>
        /// <param name='serialNo'>
        /// Serial no.
        /// </param>
        private SelectResponse sendMifareSelect(uint serialNo)
        {
            byte[] readBuffer  = new byte[64];
            int    offset      = 0;
            int    bytesToRead = 0;

            WriteCommand(Command.MIFARE_SELECT, NODE_BROADCAST, BitConverter.GetBytes(serialNo));

            //Console.WriteLine ("Card SerialNo: " + BitConverter.GetBytes(serialNo).ToHex() );

            // Naive busy way. Rewrite to consumer stream pull!
            do
            {
                Thread.Sleep(50);
                bytesToRead = port.BytesToRead;
            } while (bytesToRead == 0);

            // TODO: Use callback, make response parser able to read lazily from input stream
            int bytesRead = port.Read(readBuffer, offset, bytesToRead);

            // Evaluate data in buffer

            //Console.WriteLine ("Data received: {0} )", readBuffer.Subset(0,bytesRead).ToHex ());

            SelectResponse response = new SelectResponse();

            ushort length = readBuffer.Subset(2, 2).ToUInt16();
            //Console.WriteLine ("Length: {0} ( {1})", length, readBuffer.Subset (2, 2).ToHex ());

            ushort nodeID = readBuffer.Subset(4, 2).ToUInt16();

            //Console.WriteLine ("NodeID: {0} ( {1})", nodeID, readBuffer.Subset (4, 2).ToHex ());
            response.NodeId = nodeID;

            ushort commandCode = readBuffer.Subset(6, 2).ToUInt16();

            //Console.WriteLine ("Command: {0} ( {1})", Enum.GetName (typeof(CommandCode), commandCode), readBuffer.Subset (6, 2).ToHex ());
            response.Command = (Command)commandCode;

            byte responseCode = readBuffer[8];

            //Console.WriteLine ("Response Code: {0} ( {1})", Enum.GetName (typeof(ResponseCode), responseCode), responseCode.ToHex ());
            response.Response = (Response)responseCode;

            response.SAKByte = readBuffer[9];

            //byte checksum = readBuffer [readBuffer.Length-1]; // Hov... skal da ikke lave checksum indtil hele længden af bufferen, kun den del hvor vi har data i?!
            byte checksum = readBuffer[4 + length];

            byte calculatedChecksum = CalcCheckSum(readBuffer, 4, 4 + length);

            validateChecksum(checksum, calculatedChecksum);

            return(response);
        }
Exemple #2
0
        /// <summary>
        /// This document has some great explanations about how the auth mechanisms work on Mifare cards:
        /// http://www.metratec.com/fileadmin/docs/en/documentation/metraTec_MiFare_Protocol-Guide.pdf
        ///
        /// </summary>
        /// <returns>
        /// The auth.
        /// </returns>
        /// <param name='blockNo'>
        /// Block no.
        /// </param>
        /// <param name='authCode'>
        /// Auth code.
        /// </param>
        private MifareResponse sendAuth(byte blockNo, AuthMode authMode, byte[] authCode)
        {
            byte[] readBuffer  = new byte[64];
            int    offset      = 0;
            int    bytesToRead = 0;

            WriteCommand(Command.MIFARE_AUTHENTICATION2, NODE_BROADCAST,
                         new byte[] { (byte)authMode, blockNo }.Merge(authCode));

            // Naive busy way. Rewrite to consumer stream pull!
            do
            {
                Thread.Sleep(10);
                bytesToRead = port.BytesToRead;
            } while (bytesToRead == 0);

            // TODO: Use callback, make response parser able to read lazily from input stream
            int bytesRead = port.Read(readBuffer, offset, bytesToRead);

            // Evaluate data in buffer

            //Console.WriteLine ("Data received: {0} )", readBuffer.Subset(0,bytesRead).ToHex ());

            SelectResponse response = new SelectResponse();

            ushort length = readBuffer.Subset(2, 2).ToUInt16();
            //Console.WriteLine ("Length: {0} ( {1})", length, readBuffer.Subset (2, 2).ToHex ());

            ushort nodeID = readBuffer.Subset(4, 2).ToUInt16();

            //Console.WriteLine ("NodeID: {0} ( {1})", nodeID, readBuffer.Subset (4, 2).ToHex ());
            response.NodeId = nodeID;

            ushort commandCode = readBuffer.Subset(6, 2).ToUInt16();

            //Console.WriteLine ("Command: {0} ( {1})", Enum.GetName (typeof(CommandCode), commandCode), readBuffer.Subset (6, 2).ToHex ());
            response.Command = (Command)commandCode;

            byte responseCode = readBuffer[8];

            //Console.WriteLine ("Response Code: {0} ( {1})", Enum.GetName (typeof(ResponseCode), responseCode), responseCode.ToHex ());
            response.Response = (Response)responseCode;

            byte checksum = readBuffer[4 + length];

            byte calculatedChecksum = CalcCheckSum(readBuffer, 4, 4 + length);

            validateChecksum(checksum, calculatedChecksum);

            return(response);
        }
Exemple #3
0
        private void StartConversation(MifareTypeResponse requestResponse, MifareReadCallback callback)
        {
            sendLedRequest(LEDColor.BLUE_ON_RED_OFF);

            // Start anticollistion (and get serialNo)
            AnticollisionResponse collisionResponse = null;

            //for(int retryCount = 0; retryCount < RETRY_COUNT; retryCount++)
            {
                collisionResponse = sendMifareAnticollisionRequest();

                if (collisionResponse.Response == Response.OK)
                {
                    uint serialNo = ReverseBytes(collisionResponse.SerialNo);

                    Console.WriteLine("Card detected, type={0}, serialNo={1}",
                                      requestResponse.MifareType,
                                      serialNo);

                    SelectResponse selectResponse = sendMifareSelect(collisionResponse.SerialNo);

                    if (selectResponse.Response != Response.OK)
                    {
                        throw new Exception("Mifare select error!");
                    }
                    Console.WriteLine("Card {0} selected and active", serialNo);

                    //callback.status(BitConverter.GetBytes(collisionResponse.SerialNo).ToHex());

                    DateTime before = DateTime.Now;

                    Console.WriteLine();

                    callback.status(String.Format("Reading card {0} with serialno. {1}",
                                                  requestResponse.MifareType,
                                                  serialNo));

                    int lastAuthorizedSectorIndex = -1;

                    for (int blockIndex = 0; blockIndex < getBlockCount(requestResponse.MifareType); blockIndex++)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            // Clean up here, then...
                            //cancellationToken.ThrowIfCancellationRequested();
                            callback.status("Reading of card interupted by user!");
                            callback.error();
                            return;
                        }

                        int sectorIndex = getSectorIndexByBlockIndex(blockIndex);

                        // If we haven't authorized for this sector before
                        if (sectorIndex != lastAuthorizedSectorIndex)
                        {
                            lastAuthorizedSectorIndex = sectorIndex;

                            //Console.WriteLine("Autorizing sector {0} for block starting at index {1}", sectorIndex, blockIndex);

                            if (callback.getAuthByKeyA())
                            {
                                MifareResponse auth = sendAuth((byte)blockIndex, AuthMode.KEY_A, getRejsekortKeyByBlock(AuthMode.KEY_A, blockIndex));

                                if (auth.Response == Response.ERR_AUTH_FAILURE)
                                {
                                    var response = sendMifareRequest(MifareRequestCode.IDLE_CARD).Response;

                                    callback.status(string.Format("Error while trying to authorize sector {0} with A-key {1}",
                                                                  getSectorIndexByBlockIndex(blockIndex),
                                                                  getRejsekortKeyByBlock(AuthMode.KEY_A, blockIndex).ToHex()));
                                    callback.error();
                                    return;
                                }
                            }

                            if (callback.getAuthByKeyB())
                            {
                                MifareResponse auth = sendAuth((byte)blockIndex, AuthMode.KEY_B, getRejsekortKeyByBlock(AuthMode.KEY_B, blockIndex));

                                if (auth.Response == Response.ERR_AUTH_FAILURE)
                                {
                                    var response = sendMifareRequest(MifareRequestCode.IDLE_CARD).Response;

                                    callback.status(string.Format("Error while trying to authorize sector {0} with B-key {1}",
                                                                  getSectorIndexByBlockIndex(blockIndex),
                                                                  getRejsekortKeyByBlock(AuthMode.KEY_A, blockIndex).ToHex()));
                                    callback.error();
                                    return;
                                }
                            }
                        }

                        {
                            ReadResponse read = sendRead((byte)blockIndex);

                            // If this block is a sector trailer
                            if (getSectorIndexByBlockIndex(blockIndex + 1) != sectorIndex)
                            {
                                // If keys are supposed to be included in data
                                if (callback.getInclKeys())
                                {
                                    // If authorizing with key A is enabled
                                    if (callback.getAuthByKeyA())
                                    {
                                        Buffer.BlockCopy(callback.getKeyABySector(sectorIndex), 0, read.Data, 0, 6);
                                    }

                                    // If authorizing with key B is enabled
                                    if (callback.getAuthByKeyB())
                                    {
                                        Buffer.BlockCopy(callback.getKeyBBySector(sectorIndex), 0, read.Data, 10, 6);
                                    }
                                }
                            }

                            callback.completeBlock(blockIndex, read.Data);

                            //Console.WriteLine("Copying {0} bytes over to index {1}", 16, (blockIndex*16));

                            Buffer.BlockCopy(read.Data, 0, buffer, blockIndex * 16, 16);
                        }
                    }

                    DateTime after = DateTime.Now;

                    TimeSpan span = after - before;

                    //Console.WriteLine ("Auth took {0} ms", span.TotalMilliseconds);



                    // Done with card, halt session
                    if (sendHalt().Response == Response.OK)
                    {
                        // Turn BLUE LED on to signal All OK
                        //sendLedRequest (LEDColor.BLUE_ON_RED_OFF);

                        sendBeepRequest(BeepType.SHORT_60MS);

                        //Thread.Sleep (500);
                        // Revert to normal LED state off
                        sendLedRequest(LEDColor.ALL_LED_OFF);

                        callback.status(String.Format("Card read in {0},{1} sec.", span.Seconds, span.Milliseconds));
                    }
                    else
                    {
                        //sendLedRequest(LEDColor.RED_ON_BLUE_OFF);
                    }

                    MD5    md5  = System.Security.Cryptography.MD5.Create();
                    string hash = md5.ComputeHash(buffer).ToHex();

                    callback.success(serialNo, hash);

                    return;
                }
            };
        }