Beispiel #1
0
        public static async Task <FidoU2FHidMessage> ReadFidoU2FHidMessageAsync([NotNull] this IHidDevice device, CancellationToken cancellationToken)
        {
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }

            var initReport = await device.GetInputReportAsync(cancellationToken);

            var init = InitializationPacket.ReadFrom(initReport.Data);

            var  dataSizeReceived = init.Data.Count;
            var  continuations    = new List <ContinuationPacket>();
            byte index            = 0;

            while (dataSizeReceived < init.PayloadLength)
            {
                var continuationReport = await device.GetInputReportAsync(cancellationToken);

                var continuation = ContinuationPacket.ReadFrom(continuationReport.Data, init.PayloadLength - dataSizeReceived);
                if (continuation.PaketSequence != index)
                {
                    throw new InvalidSequenceNumberException(continuationReport.Data,
                                                             $"The sequence number isn't the expected one, expected {index} but read {continuation.PaketSequence}");
                }
                continuations.Add(continuation);
                dataSizeReceived += continuation.Data.Count;
                index            += 1;
            }

            return(BuildMessage(init, continuations));
        }
Beispiel #2
0
        static unsafe void Test(Win32HidDevice device)
        {
            var init = new InitializationPacket();

            init.CommandIdentifier = (byte)U2FHidCommand.Init;
            init.ChannelIdentifier = U2FHID_BROADCAST_CID;
            init.PayloadLength     = 8;
            var caps = device.Information.Capabilities;

            var buffer = new byte[caps.InputReportByteLength];

            fixed(byte *pBuffer = buffer)
            {
                Marshal.StructureToPtr(init, new IntPtr(pBuffer + 1), false);

                buffer[0]  = 0x00;
                buffer[8]  = 0xCA;
                buffer[9]  = 0xFE;
                buffer[10] = 0xBA;
                buffer[11] = 0xBE;
                buffer[12] = 0xDE;
                buffer[13] = 0xAD;
                buffer[14] = 0xBA;
                buffer[15] = 0xBE;

                WriteBuffer(buffer);

                var task   = Kernel32Dll.WriteFileAsync(device.Handle, new IntPtr(pBuffer), buffer.Length);
                var writen = task.Result;

                Console.WriteLine("Writen {0} bytes", writen);
            }

            var bufferOut = new byte[caps.OutputReportByteLength];

            fixed(byte *pBuffer = bufferOut)
            {
                var intPtr = new IntPtr(pBuffer);
                var task   = Kernel32Dll.ReadFileAsync(device.Handle, intPtr, bufferOut.Length);
                var read   = task.Result;

                Console.WriteLine("Read {0} bytes", read);
            }

            WriteBuffer(bufferOut);

            Wink(device, bufferOut[16], bufferOut[17], bufferOut[18], bufferOut[19]);
        }
Beispiel #3
0
        static Tuple <InitializationPacket, List <ContinuationPacket> > MakeOutputPackets(
            int paketLength, FidoU2FHidMessage message)
        {
            var availableInInit         = paketLength - InitializationPacket.NoDataSize;
            var availableInContinuation = paketLength - ContinuationPacket.NoDataSize;
            var data = message.Data;

            var init = new InitializationPacket
            {
                ChannelIdentifier = message.Channel,
                CommandIdentifier = (byte)message.Command,
                PayloadLength     = (ushort)data.Count,
                Data = new ArraySegment <byte>(data.Array, data.Offset,
                                               Math.Min(data.Count, availableInInit))
            };

            var  sizeHandled   = init.Data.Count;
            var  continuations = new List <ContinuationPacket>();
            byte sequence      = 0;

            while (sizeHandled < data.Count)
            {
                var continuation = new ContinuationPacket
                {
                    ChannelIdentifier = message.Channel,
                    PaketSequence     = sequence,
                    Data = new ArraySegment <byte>(data.Array, data.Offset + sizeHandled,
                                                   Math.Min(data.Count - sizeHandled, availableInContinuation))
                };

                continuations.Add(continuation);

                sizeHandled += continuation.Data.Count;
                sequence    += 1;
            }

            return(Tuple.Create(init, continuations));
        }
Beispiel #4
0
        static FidoU2FHidMessage BuildMessage(InitializationPacket init, List <ContinuationPacket> continuations)
        {
            ArraySegment <byte> data;

            if (continuations.Count > 0)
            {
                // We must allocate memory to reconstruct the message
                var stream = new MemoryStream(init.PayloadLength);
                stream.Write(init.Data.Array, init.Data.Offset, init.Data.Count);
                foreach (var continuation in continuations)
                {
                    stream.Write(continuation.Data.Array, continuation.Data.Offset, continuation.Data.Count);
                }
                data = stream.ToArray().Segment();
            }
            else
            {
                // No need to reconstruct the message
                data = init.Data;
            }

            return(new FidoU2FHidMessage(init.ChannelIdentifier, (U2FHidCommand)init.CommandIdentifier, data));
        }