Beispiel #1
0
        /// <summary>
        /// Sends an APDU to the device, and waits for a response
        /// </summary>
        public async Task <byte[]> SendApduAsync(byte ins, byte p1 = 0x00, byte p2 = 0x00, byte[] data = null)
        {
            if (data == null)
            {
                data = new byte[0];
            }
            var size = data.Length;
            var l0   = (byte)(size >> 16 & 0xff);
            var l1   = (byte)(size >> 8 & 0xff);
            var l2   = (byte)(size & 0xff);

            var byteArrayBuilder = new ByteArrayBuilder();

            byteArrayBuilder.Append(new byte[] { 0x00, ins, p1, p2, l0, l1, l2 });
            byteArrayBuilder.Append(data);
            byteArrayBuilder.Append(new byte[] { 0x04, 0x00 });

            var apduData = byteArrayBuilder.GetBytes();

            var response = await DoSendApduAsync(apduData);

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

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

            if (statusCode != Constants.APDU_OK)
            {
                throw new ApduException(statusCode);
            }

            return(responseData);
        }
Beispiel #2
0
        public static async Task <AuthenticateResponse> AuthenticateAsync(U2FHidDevice u2fHidDevice, StartedAuthentication request, string facet, bool checkOnly)
        {
            ValidateRequest(request, facet);

            var sha256   = new SHA256Managed();
            var appParam = sha256.ComputeHash(Encoding.ASCII.GetBytes(request.AppId));

            var clientDataString = GetAuthenticationClientData(request.Challenge, facet);
            var clientParam      = sha256.ComputeHash(Encoding.ASCII.GetBytes(clientDataString));

            var keyHandleDecoded = Utils.Base64StringToByteArray(request.KeyHandle);

            var byteArrayBuilder = new ByteArrayBuilder();

            byteArrayBuilder.Append(clientParam);
            byteArrayBuilder.Append(appParam);
            byteArrayBuilder.Append((byte)keyHandleDecoded.Length);
            byteArrayBuilder.Append(keyHandleDecoded);

            var data = byteArrayBuilder.GetBytes();
            var p1   = (byte)(checkOnly ? 0x07 : 0x03);
            var p2   = (byte)0x00;

            var response = await u2fHidDevice.SendApduAsync(Constants.INS_SIGN, p1, p2, data);

            var responseBase64   = Utils.ByteArrayToBase64String(response);
            var clientDataBase64 = Utils.ByteArrayToBase64String(Encoding.ASCII.GetBytes(clientDataString));

            var authenticateResponse = new AuthenticateResponse(clientDataBase64, responseBase64, request.KeyHandle);

            return(authenticateResponse);
        }
        private async Task <byte[]> ReadResponseAsync(byte command)
        {
            //Log.Debug("ReadResponse");

            //var reportSize = hidDevice.Capabilities.OutputReportByteLength;
            var reportSize = HID_RPT_SIZE;

            var byteArrayBuilder = new ByteArrayBuilder();

            byteArrayBuilder.Append(cid);
            byteArrayBuilder.Append((byte)(TYPE_INIT | command));

            var resp   = Encoding.ASCII.GetBytes(".");
            var header = byteArrayBuilder.GetBytes();

            HidReport report = null;

            while (!resp.Take(header.Length).SequenceEqual(header))
            {
                report = await hidDevice.ReadReportAsync(HidTimeoutMs);

                if (report.ReadStatus != HidDeviceData.ReadStatus.Success)
                {
                    throw new Exception("Error reading from device");
                }

                resp = report.Data;

                byteArrayBuilder.Clear();
                byteArrayBuilder.Append(cid);
                byteArrayBuilder.Append(STAT_ERR);

                if (resp.Take(header.Length).SequenceEqual(byteArrayBuilder.GetBytes()))
                {
                    throw new Exception("Error in response header");
                }
            }

            var dataLength = (report.Data[5] << 8) + report.Data[6];

            var payloadData = report.Data.Skip(7).Take(Math.Min(dataLength, reportSize)).ToArray();

            //Log.Debug($"Payload data: {BitConverter.ToString(payloadData)}");

            byteArrayBuilder.Clear();
            byteArrayBuilder.Append(payloadData);
            dataLength -= (int)byteArrayBuilder.Length;

            var seq = 0;

            while (dataLength > 0)
            {
                report = await hidDevice.ReadReportAsync(HidTimeoutMs);

                if (report.ReadStatus != HidDeviceData.ReadStatus.Success)
                {
                    throw new Exception("Error reading from device");
                }

                if (!report.Data.Take(4).SequenceEqual(cid))
                {
                    throw new Exception("Wrong CID from device");
                }
                if (report.Data[4] != (byte)(seq & 0x7f))
                {
                    throw new Exception("Wrong SEQ from device");
                }
                seq++;
                payloadData = report.Data.Skip(5).Take(Math.Min(dataLength, reportSize)).ToArray();
                //Log.Debug($"Payload data: {BitConverter.ToString(payloadData)}");

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

            var result = byteArrayBuilder.GetBytes();

            return(result);
        }
        private async Task SendRequestAsync(byte command, byte[] data = null)
        {
            //Log.Debug($"SendRequest: {command:X2}");

            if (data == null)
            {
                data = new byte[0];
            }

            //Log.Debug($"Data: {BitConverter.ToString(data)}");

            //var reportSize = hidDevice.Capabilities.InputReportByteLength;
            var reportSize = HID_RPT_SIZE;

            var size        = data.Length;
            var bc_l        = (byte)(size & 0xff);
            var bc_h        = (byte)(size >> 8 & 0xff);
            var payloadData = data.Take(reportSize - 7).ToArray();

            //Log.Debug($"Payload data: {BitConverter.ToString(payloadData)}");

            var payloadBuilder = new ByteArrayBuilder();

            payloadBuilder.Append(cid);
            payloadBuilder.Append((byte)(TYPE_INIT | command));
            payloadBuilder.Append(bc_h);
            payloadBuilder.Append(bc_l);
            payloadBuilder.Append(payloadData);
            while (payloadBuilder.Length < reportSize)
            {
                payloadBuilder.Append(0x00);
            }

            var payload = payloadBuilder.GetBytes();
            var report  = hidDevice.CreateReport();

            report.Data = payload;
            await hidDevice.WriteReportAsync(report, HidTimeoutMs);

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

            while (remainingData.Length > 0)
            {
                payloadData = remainingData.Take(reportSize - 5).ToArray();
                //Log.Debug($"Payload data: {BitConverter.ToString(payloadData)}");

                payloadBuilder.Clear();
                payloadBuilder.Append(cid);
                payloadBuilder.Append((byte)(0x7f & seq));
                payloadBuilder.Append(payloadData);
                while (payloadBuilder.Length < reportSize)
                {
                    payloadBuilder.Append(0x00);
                }

                payload     = payloadBuilder.GetBytes();
                report      = hidDevice.CreateReport();
                report.Data = payload;
                if (!await hidDevice.WriteReportAsync(report, HidTimeoutMs))
                {
                    throw new Exception("Error writing to device");
                }

                remainingData = remainingData.Skip(reportSize - 5).ToArray();
                seq++;
            }
        }