/// <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); }
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++; } }