private async Task <ApduResponse> U2F_Authenticate(byte[] clientDataHash, byte[] appIdHash, byte[] keyHandle, bool checkOnly) { var request = new ApduRequest { Ins = (byte)CTAP1_INS.Authenticate, P1 = checkOnly ? (byte)0x07 : (byte)0x03, data = clientDataHash.Concat(appIdHash).Concat(Enumerable.Repeat((byte)keyHandle.Length, 1)).Concat(keyHandle).ToArray() }; return(await Apdu.SendAdpu(_connection, request)); }
public static async Task <ApduResponse> SendAdpu(Stream connection, ApduRequest request) { var dataLen = (ushort)(request.data?.Length ?? 0); var maxRsBytes = 2; if (request.maxResponseSize.HasValue) { var rss = request.maxResponseSize.Value; if (rss == 0) { maxRsBytes = 0; } else if (rss <= 0xff) { maxRsBytes = 1; } else { maxRsBytes = 2; } } var packetLength = 1 + 1 + 2 + (dataLen == 0 ? 0 : (dataLen <= 0xff ? 1 : 3)) + dataLen + maxRsBytes; var packet = new byte[packetLength]; packet[0] = request.Cla; packet[1] = request.Ins; packet[2] = request.P1; packet[3] = request.P2; if (dataLen > 0) { byte dataOffset = 4; if (dataOffset <= 0xff) { packet[4] = (byte)(dataOffset & 0xff); dataOffset += 1; } else { packet[4] = 0; packet[5] = (byte)((dataLen >> 8) & 0xff); packet[6] = (byte)(dataLen & 0xff); dataOffset += 3; } Array.Copy(request.data, 0, packet, dataOffset, request.data?.Length ?? 0); } if (request.maxResponseSize.HasValue) { if (maxRsBytes == 1) { packet[packet.Length - 1] = (byte)(request.maxResponseSize.Value & 0xff); } else if (maxRsBytes == 2) { packet[packet.Length - 1] = (byte)(request.maxResponseSize.Value & 0xff); packet[packet.Length - 2] = (byte)((request.maxResponseSize.Value >> 8) & 0xff); } } await connection.WriteAsync(packet, 0, packet.Length); await connection.FlushAsync(); var readBuffer = new byte[maxRsBytes >= 2 ? ushort.MaxValue : byte.MaxValue]; var bytesRead = await connection.ReadAsync(readBuffer, 0, readBuffer.Length); var rs = new ApduResponse { SW1 = 6 }; if (bytesRead >= 2) { rs.SW1 = readBuffer[bytesRead - 2]; rs.SW2 = readBuffer[bytesRead - 1]; if (bytesRead > 2) { rs.data = new byte[bytesRead - 2]; Array.Copy(readBuffer, 0, rs.data, 0, rs.data.Length); } } return(rs); }