def _read_resp(self, cid, cmd):
        resp = b'.'
        header = cid + int2byte(TYPE_INIT | cmd)
        while resp and resp[:5] != header:
            resp_vals = _read_timeout(self.handle, HID_RPT_SIZE)
            resp = b''.join(int2byte(v) for v in resp_vals)
            if resp[:5] == cid + int2byte(STAT_ERR):
                raise U2FHIDError(byte2int(resp[7]))

        if not resp:
            raise exc.DeviceError("Invalid response from device!")

        data_len = (byte2int(resp[5]) << 8) + byte2int(resp[6])
        data = resp[7:min(7 + data_len, HID_RPT_SIZE)]
        data_len -= len(data)

        seq = 0
        while data_len > 0:
            resp_vals = _read_timeout(self.handle, HID_RPT_SIZE)
            resp = b''.join(int2byte(v) for v in resp_vals)
            if resp[:4] != cid:
                raise exc.DeviceError("Wrong CID from device!")
            if byte2int(resp[4]) != seq & 0x7f:
                raise exc.DeviceError("Wrong SEQ from device!")
            seq += 1
            new_data = resp[5:min(5 + data_len, HID_RPT_SIZE)]
            data_len -= len(new_data)
            data += new_data
        return data
Beispiel #2
0
    def _read_resp(self, cid, cmd):
        resp = '.'
        header = cid + chr(TYPE_INIT | cmd)
        while resp and resp[:5] != header:
            resp = ''.join(map(chr, _read_timeout(self.handle, HID_RPT_SIZE)))
            if resp[:5] == cid + chr(STAT_ERR):
                raise U2FHIDError(ord(resp[6]))

        if not resp:
            raise exc.DeviceError("Invalid response from device!")

        data_len = (ord(resp[5]) << 8) + ord(resp[6])
        data = resp[7:min(7 + data_len, HID_RPT_SIZE)]
        data_len -= len(data)

        seq = 0
        while data_len > 0:
            resp = ''.join(map(chr, _read_timeout(self.handle, HID_RPT_SIZE)))
            if resp[:4] != cid:
                raise exc.DeviceError("Wrong CID from device!")
            if ord(resp[4]) != seq & 0x7f:
                raise exc.DeviceError("Wrong SEQ from device!")
            seq += 1
            new_data = resp[5:min(5 + data_len, HID_RPT_SIZE)]
            data_len -= len(new_data)
            data += new_data
        return data
Beispiel #3
0
    def send_apdu(self, ins, p1=0, p2=0, data=b''):
        """
        Sends an APDU to the device, and waits for a response.
        """
        if data is None:
            data = b''
        elif isinstance(data, int):
            data = int2byte(data)

        size = len(data)
        l0 = size >> 16 & 0xff
        l1 = size >> 8 & 0xff
        l2 = size & 0xff
        apdu_data = struct.pack('B B B B B B B %is B B' % size, 0, ins, p1, p2,
                                l0, l1, l2, data, 0x04, 0x00)
        try:
            resp = self._do_send_apdu(apdu_data)
        except Exception as e:
            # TODO Use six.reraise if/when Six becomes an agreed dependency.
            raise exc.DeviceError(e)
        status = struct.unpack('>H', resp[-2:])[0]
        data = resp[:-2]
        if status != APDU_OK:
            raise exc.APDUError(status)
        return data
Beispiel #4
0
    def send_apdu(self, ins, p1=0, p2=0, data=''):
        """
        Sends an APDU to the device, and waits for a response.
        """
        if data is None:
            data = ''
        elif isinstance(data, int):
            data = chr(data)

        size = len(data)
        l0 = size >> 16 & 0xff
        l1 = size >> 8 & 0xff
        l2 = size & 0xff
        apdu_data = "%c%c%c%c%c%c%c%s%c%c" % \
            (0, ins, p1, p2, l0, l1, l2, data, 0x04, 0x00)
        try:
            resp = self._do_send_apdu(apdu_data)
        except Exception as e:
            # Wrap exception, keeping trace
            raise exc.DeviceError(e), None, sys.exc_info()[2]
        status = int(resp[-2:].encode('hex'), 16)
        data = resp[:-2]
        if status != APDU_OK:
            raise exc.APDUError(status)
        return data
Beispiel #5
0
 def _send_req(self, cid, cmd, data):
     size = len(data)
     bc_l = int2byte(size & 0xff)
     bc_h = int2byte(size >> 8 & 0xff)
     payload = cid + int2byte(TYPE_INIT | cmd) + bc_h + bc_l + \
         data[:HID_RPT_SIZE - 7]
     payload += b'\0' * (HID_RPT_SIZE - len(payload))
     if self.handle.write([0] + [byte2int(c) for c in payload]) < 0:
         raise exc.DeviceError("Cannot write to device!")
     data = data[HID_RPT_SIZE - 7:]
     seq = 0
     while len(data) > 0:
         payload = cid + int2byte(0x7f & seq) + data[:HID_RPT_SIZE - 5]
         payload += b'\0' * (HID_RPT_SIZE - len(payload))
         if self.handle.write([0] + [byte2int(c) for c in payload]) < 0:
             raise exc.DeviceError("Cannot write to device!")
         data = data[HID_RPT_SIZE - 5:]
         seq += 1
    def _write_to_device(self, to_send, timeout=2.0):
        expected = len(to_send)
        actual = 0
        stop_at = time() + timeout
        while actual != expected:
            if (time() > stop_at):
                raise exc.DeviceError("Unable to send data to the device")

            actual = self.handle.write(to_send)
            sleep(0.025)
    def init(self):
        nonce = os.urandom(8)
        resp = self.call(CMD_INIT, nonce)

        timeout = time() + 2.0
        while (len(resp) != 17 or resp[:8] != nonce):
            if timeout < time():
                raise exc.DeviceError('Wrong INIT response from device')
            sleep(0.1)
            resp = self._read_resp(self.cid, CMD_INIT)

        self.cid = resp[8:12]
        self.capabilities = byte2int(resp[16])
 def ping(self, msg=b'Hello U2F'):
     resp = self.call(CMD_PING, msg)
     if resp != msg:
         raise exc.DeviceError("Incorrect PING readback")
     return resp