Example #1
0
        private async Task SendRequestAsync(FidoHidMsgType msgType, byte[] data = null)
        {
            if (data == null)
            {
                data = new byte[0];
            }

            var size        = data.Length;
            var payloadData = data.Take(HidReportSize - 7).ToArray();

            var payloadBuilder = new ByteArrayBuilder();

            payloadBuilder.Append(_channelId);
            payloadBuilder.Append((byte)msgType);
            payloadBuilder.Append((byte)(size >> 8 & 0xff));
            payloadBuilder.Append((byte)(size & 0xff));
            payloadBuilder.Append(payloadData);
            payloadBuilder.AppendZerosTill(HidReportSize);


            var report = _hidDevice.CreateReport();

            report.Data = payloadBuilder.GetBytes();
            if (!await _hidDevice.WriteReportAsync(report, HidTimeoutMs).ConfigureAwait(false))
            {
                throw new FidoException(FidoError.InterruptedIO, "Error writing to token");
            }

            var remainingData = data.Skip(HidReportSize - 7).ToArray();
            var seq           = 0;

            while (remainingData.Length > 0)
            {
                payloadData = remainingData.Take(HidReportSize - 5).ToArray();

                payloadBuilder.Clear();
                payloadBuilder.Append(_channelId);
                payloadBuilder.Append((byte)(0x7f & seq));
                payloadBuilder.Append(payloadData);
                payloadBuilder.AppendZerosTill(HidReportSize);

                report      = _hidDevice.CreateReport();
                report.Data = payloadBuilder.GetBytes();
                if (!await _hidDevice.WriteReportAsync(report, HidTimeoutMs).ConfigureAwait(false))
                {
                    throw new FidoException(FidoError.InterruptedIO, "Error writing to token");
                }

                remainingData = remainingData.Skip(HidReportSize - 5).ToArray();
                seq++;
            }
        }
Example #2
0
        public byte[] GetBytes()
        {
            var  bytes       = _byteArrayBuilder.GetBytes();
            var  outBytes    = new ByteArrayBuilder();
            byte currentByte = 0;
            var  currentBit  = 7;

            for (int i = 0; i < _byteArrayBuilder.Length; i++)
            {
                currentByte |= (byte)(bytes[i] << currentBit);
                currentBit--;
                if (currentBit < 0)
                {
                    outBytes.Append(currentByte);
                    currentByte = 0;
                    currentBit  = 7;
                }
            }

            if (currentBit < 7)
            {
                outBytes.Append(currentByte);
            }

            return(outBytes.GetBytes());
        }
Example #3
0
        public async Task <byte[]> ApduMessageAsync(FidoInstruction instruction, FidoParam1 param1 = FidoParam1.None, FidoParam2 param2 = FidoParam2.None, byte[] data = null)
        {
            if (data == null)
            {
                data = new byte[0];
            }
            var dataLen = data.Length;
            var adpu    = new ByteArrayBuilder();

            adpu.Append(new byte[]
            {
                0x00, //CLA byte
                (byte)instruction,
                (byte)param1,
                (byte)param2,
                //some tokens only work with extended length
                (byte)(dataLen >> 16 & 0xff),
                (byte)(dataLen >> 8 & 0xff),
                (byte)(dataLen & 0xff)
            });
            adpu.Append(data);

            //max response size: 65536 byte
            //needed for hyperfido
            adpu.Append(new byte[] { 0x00, 0x00 });

            var apduData = adpu.GetBytes();

            var response = await CallAsync(FidoHidMsgType.ApduMessage, apduData).ConfigureAwait(false);

            var responseData = response.Take(response.Length - 2).ToArray();
            var status       = response.Skip(response.Length - 2).Take(2).Reverse().ToArray();

            var statusCode = (FidoApduResponse)BitConverter.ToUInt16(status, 0);

            if (statusCode != FidoApduResponse.Ok)
            {
                throw new FidoException(statusCode);
            }

            return(responseData);
        }
Example #4
0
        private async Task <byte[]> ReadResponseAsync(FidoHidMsgType msgType)
        {
            HidReport      report;
            FidoHidMsgType recvdMsgType;

            do
            {
                report = await _hidDevice.ReadReportAsync(HidTimeoutMs).ConfigureAwait(false);

                if (report.ReadStatus != HidDeviceData.ReadStatus.Success)
                {
                    throw new FidoException(FidoError.InterruptedIO, $"Error reading from token: {report.ReadStatus}");
                }
            } while (!CheckHeader(report.Data, out recvdMsgType));

            if (msgType != recvdMsgType)
            {
                throw new FidoException(FidoError.ProtocolViolation, $"received {recvdMsgType} instead of {msgType}");
            }

            var dataLength  = (report.Data[5] << 8) + report.Data[6];
            var payloadData = report.Data.Skip(7).Take(Math.Min(dataLength, HidReportSize)).ToArray();

            var payload = new ByteArrayBuilder();

            payload.Append(payloadData);
            dataLength -= (int)payload.Length;

            var seq = 0;

            while (dataLength > 0)
            {
                do
                {
                    report = await _hidDevice.ReadReportAsync(HidTimeoutMs).ConfigureAwait(false);

                    if (report.ReadStatus != HidDeviceData.ReadStatus.Success)
                    {
                        throw new FidoException(FidoError.InterruptedIO, $"Error reading from token: {report.ReadStatus}");
                    }
                } while (!CheckHeader(report.Data, out recvdMsgType));

                if ((recvdMsgType & FidoHidMsgType.CommandFlag) > 0)
                {
                    throw new FidoException(FidoError.ProtocolViolation, "fragmented message continuation had command flag set");
                }

                if ((byte)recvdMsgType != (seq & (byte)FidoHidMsgType.SequenceIdMask))
                {
                    throw new FidoException(FidoError.ProtocolViolation, $"received out-of-sequence message: Recvd:0x{(byte)recvdMsgType:X}, seq-nr:{seq}");
                }

                seq++;
                payloadData = report.Data.Skip(5).Take(Math.Min(dataLength, HidReportSize)).ToArray();

                dataLength -= payloadData.Length;
                payload.Append(payloadData);
            }

            return(payload.GetBytes());
        }