예제 #1
0
        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));
        }
예제 #2
0
        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);
        }