Example #1
0
    def test_03(self, llc):
        """Version handling"""

        bt_record = ndef.BluetoothEasyPairingRecord('01:02:03:04:05:06')
        bt_record.name = 'carrier-1'

        client = handover_connect(llc, self.options)
        try:
            info("send handover request message with version 1.2")
            hr_record = ndef.HandoverRequestRecord('1.2', os.urandom(2))
            hr_record.add_alternative_carrier('active', bt_record.name)
            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            if records[0].version_string != "1.2":
                raise TestFail("handover select message version is not 1.2")
            info("received handover select message version 1.2")
        finally:
            client.close()

        client = handover_connect(llc, self.options)
        try:
            info("send handover request message with version 1.1")
            hr_record = ndef.HandoverRequestRecord('1.1', os.urandom(2))
            hr_record.add_alternative_carrier('active', bt_record.name)
            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            if records[0].version_string != "1.2":
                raise TestFail("handover select message version is not 1.2")
            info("received handover select message version 1.2")
        finally:
            client.close()

        client = handover_connect(llc, self.options)
        try:
            info("send handover request message with version 1.15")
            hr_record = ndef.HandoverRequestRecord('1.15', os.urandom(2))
            hr_record.add_alternative_carrier('active', bt_record.name)
            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            if records[0].version_string != "1.2":
                raise TestFail("handover select message version is not 1.2")
            info("received handover select message version 1.2")
        finally:
            client.close()

        client = handover_connect(llc, self.options)
        try:
            info("send handover request message with version 15.0")
            hr_record = ndef.HandoverRequestRecord('15.0', os.urandom(2))
            hr_record.add_alternative_carrier('active', bt_record.name)
            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            if records[0].version_string != "1.2":
                raise TestFail("handover select message version is not 1.2")
            info("received handover select message version 1.2")
        finally:
            client.close()
Example #2
0
    def test_08(self, llc):
        """Skip meaningless records"""

        client = handover_connect(llc, self.options)
        try:
            bt_record = ndef.BluetoothEasyPairingRecord("01:02:03:04:05:06")
            bt_record.name = "carrier-1"
            bt_record.device_name = "Handover Test Client"
            bt_record.device_class = 0x10010C
            bt_record.add_service_class(0x1105)
            bt_record.add_service_class(0x1106)

            hr_record = ndef.HandoverRequestRecord("1.2", os.urandom(2))
            hr_record.add_alternative_carrier("active", bt_record.name)

            handover_send(client, [hr_record, ndef.TextRecord("X"), bt_record])
            records = handover_recv(client, timeout=3.0)
            info("received {}".format(records[0].type))
            hs_record, bt_record = records

            if len(hs_record.alternative_carriers) != 1:
                raise TestFail("one selected carrier is expected")
            if bt_record.type != "application/vnd.bluetooth.ep.oob":
                raise TestFail("a Bluetooth carrier is expected")
        finally:
            client.close()
Example #3
0
    def test_02(self, llc):
        """Empty carrier list"""

        client = handover_connect(llc, self.options)
        try:
            hr_record = ndef.HandoverRequestRecord("1.2", os.urandom(2))
            handover_send(client, [hr_record])
            records = handover_recv(client, timeout=3.0)
            if len(records[0].alternative_carriers) > 0:
                raise TestFail("handover select message returned carriers")
        finally:
            client.close()
Example #4
0
    def test_07(self, llc):
        """Two handover requests"""

        client = handover_connect(llc, self.options)
        try:
            unknown_carrier = "urn:nfc:ext:nfcpy.org:unknown-carrier-type"
            records = [
                ndef.HandoverRequestRecord("1.2", os.urandom(2)),
                ndef.Record(unknown_carrier, "unknown-carrier")
            ]
            records[0].add_alternative_carrier("active", records[1].name)

            info("request carrier {}".format(records[1].type))
            handover_send(client, records)
            records = handover_recv(client, timeout=3.0)
            info("received {}".format(records[0].type))

            if records[0].version_info.major != 1:
                raise TestFail("handover major version is not 1")
            if len(records[0].alternative_carriers) != 0:
                raise TestFail("an empty carrier selection is expected first")

            bt_record = ndef.BluetoothEasyPairingRecord("01:02:03:04:05:06")
            bt_record.name = "carrier-1"
            bt_record.device_name = "Handover Test Client"
            bt_record.device_class = 0x10010C
            bt_record.add_service_class(0x1105)
            bt_record.add_service_class(0x1106)

            hr_record = ndef.HandoverRequestRecord("1.2", os.urandom(2))
            hr_record.add_alternative_carrier("active", bt_record.name)

            info("propose carrier {}".format(bt_record.type))
            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            info("received {}".format(records[0].type))

        finally:
            client.close()
Example #5
0
    def test_05(self, llc):
        """Bluetooth secure pairing"""

        client = handover_connect(llc, self.options)
        try:
            bt_record = ndef.BluetoothEasyPairingRecord("01:02:03:04:05:06")
            bt_record.name = "carrier-1"
            bt_record.device_name = "Handover Test Client"
            bt_record.device_class = 0x10010C
            bt_record.add_service_class(0x1105)
            bt_record.add_service_class(0x1106)
            bt_record.simple_pairing_hash_256 = \
                0x1234567890ABCDEF1234567890ABCDEF
            bt_record.simple_pairing_randomizer_256 = \
                0x010203040506070809000A0B0C0D0E0F

            hr_record = ndef.HandoverRequestRecord("1.2", os.urandom(2))
            hr_record.add_alternative_carrier("active", bt_record.name)

            handover_send(client, [hr_record, bt_record])
            records = handover_recv(client, timeout=3.0)
            info("received {}".format(records[0].type))
            hs_record, bt_record = records

            if len(hs_record.alternative_carriers) != 1:
                raise TestFail("one selected carrier is expected")
            if bt_record.type != "application/vnd.bluetooth.ep.oob":
                raise TestFail("a Bluetooth carrier is expected")
            if bt_record.device_name is None:
                if self.options.relax:
                    log.warning("no local device name attribute")
                else:
                    raise TestFail("no local device name attribute")
            if bt_record.device_name == "":
                raise TestFail("empty local device name attribute")
            if bt_record.device_class is None:
                log.warning("there is no class of device attribute")
            if len(bt_record.service_class_list) == 0:
                log.warning("there are no service class UUIDs")
            if bt_record.simple_pairing_hash_256 is None:
                if self.options.relax:
                    log.warning("ssp hash required for secure pairing")
                else:
                    raise TestFail("ssp hash required for secure pairing")
            if bt_record.simple_pairing_randomizer_256 is None:
                if self.options.relax:
                    log.warning("ssp rand required for secure pairing")
                else:
                    raise TestFail("ssp rand required for secure pairing")
        finally:
            client.close()
Example #6
0
    def test_06(self, llc):
        """Unknown carrier type"""

        client = handover_connect(llc, self.options)
        try:
            unknown_carrier = "urn:nfc:ext:nfcpy.org:unknown-carrier-type"
            records = [
                ndef.HandoverRequestRecord("1.2", os.urandom(2)),
                ndef.Record(unknown_carrier, "unknown-carrier")
            ]
            records[0].add_alternative_carrier("active", records[1].name)

            handover_send(client, records)
            records = handover_recv(client, timeout=3.0)
            info("received {}".format(records[0].type))

            if records[0].version_info.major != 1:
                raise TestFail("handover major version is not 1")
            if len(records[0].alternative_carriers) != 0:
                raise TestFail("an empty carrier selection is expected")
        finally:
            client.close()
Example #7
0
def dpp_handover_client(llc):
    uri = wpas_get_nfc_uri(start_listen=False)
    uri = ndef.UriRecord(uri)
    print("NFC URI record for DPP: " + str(uri))
    carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
    hr = ndef.HandoverRequestRecord(version="1.4", crn=os.urandom(2))
    hr.add_alternative_carrier('active', carrier.name)
    message = [hr, carrier]
    print("NFC Handover Request message for DPP: " + str(message))

    client = nfc.handover.HandoverClient(llc)
    try:
        summary("Trying to initiate NFC connection handover")
        client.connect()
        summary("Connected for handover")
    except nfc.llcp.ConnectRefused:
        summary("Handover connection refused")
        client.close()
        return
    except Exception as e:
        summary("Other exception: " + str(e))
        client.close()
        return

    summary("Sending handover request")

    if not client.send_records(message):
        summary("Failed to send handover request")
        client.close()
        return

    summary("Receiving handover response")
    message = client.recv_records(timeout=3.0)
    if message is None:
        summary("No response received")
        client.close()
        return
    print("Received message: " + str(message))
    if len(message) < 1 or \
       not isinstance(message[0], ndef.HandoverSelectRecord):
        summary("Response was not Hs - received: " + message.type)
        client.close()
        return

    print("Received message")
    print("alternative carriers: " + str(message[0].alternative_carriers))

    dpp_found = False
    for carrier in message:
        if isinstance(carrier, ndef.HandoverSelectRecord):
            continue
        print("Remote carrier type: " + carrier.type)
        if carrier.type == "application/vnd.wfa.dpp":
            if len(carrier.data) == 0 or carrier.data[0] != 0:
                print("URI Identifier Code 'None' not seen")
                continue
            print("DPP carrier type match - send to wpa_supplicant")
            dpp_found = True
            uri = carrier.data[1:].decode("utf-8")
            print("DPP URI: " + uri)
            res = wpas_report_handover_sel(uri)
            if res is None or "FAIL" in res:
                summary("DPP handover report rejected")
                break

            success_report("DPP handover reported successfully (initiator)")
            print("peer_id=" + res)
            peer_id = int(res)
            # TODO: Single Configurator instance
            wpas = wpas_connect()
            if wpas is None:
                break
            res = wpas.request("DPP_CONFIGURATOR_ADD")
            if "FAIL" in res:
                print("Failed to initiate Configurator")
                break
            conf_id = int(res)
            global own_id
            print("Initiate DPP authentication")
            cmd = "DPP_AUTH_INIT peer=%d own=%d conf=sta-dpp configurator=%d" % (
                peer_id, own_id, conf_id)
            res = wpas.request(cmd)
            if "FAIL" in res:
                print("Failed to initiate DPP authentication")
            break

    if not dpp_found:
        print(
            "DPP carrier not seen in response - allow peer to initiate a new handover with different parameters"
        )
        client.close()
        print("Returning from dpp_handover_client")
        return

    print("Remove peer")
    client.close()
    print("Done with handover")
    global only_one
    if only_one:
        print("only_one -> stop loop")
        global continue_loop
        continue_loop = False

    global no_wait
    if no_wait:
        print("Trying to exit..")
        global terminate_now
        terminate_now = True

    print("Returning from dpp_handover_client")
Example #8
0
def dpp_handover_client(llc):
    uri = wpas_get_nfc_uri(start_listen=False)
    if uri is None:
        summary("Cannot start handover client - no bootstrap URI available")
        return
    uri = ndef.UriRecord(uri)
    summary("NFC URI record for DPP: " + str(uri))
    carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
    crn = os.urandom(2)
    hr = ndef.HandoverRequestRecord(version="1.4", crn=crn)
    hr.add_alternative_carrier('active', carrier.name)
    message = [hr, carrier]
    summary("NFC Handover Request message for DPP: " + str(message))

    global peer_crn
    if peer_crn is not None:
        summary(
            "NFC handover request from peer was already received - do not send own"
        )
        return
    client = nfc.handover.HandoverClient(llc)
    try:
        summary("Trying to initiate NFC connection handover")
        client.connect()
        summary("Connected for handover")
    except nfc.llcp.ConnectRefused:
        summary("Handover connection refused")
        client.close()
        return
    except Exception as e:
        summary("Other exception: " + str(e))
        client.close()
        return

    if peer_crn is not None:
        summary(
            "NFC handover request from peer was already received - do not send own"
        )
        client.close()
        return

    summary("Sending handover request")

    global my_crn, my_crn_ready, hs_sent
    my_crn_ready = True

    if not client.send_records(message):
        my_crn_ready = False
        summary("Failed to send handover request")
        client.close()
        return

    my_crn, = struct.unpack('>H', crn)

    summary("Receiving handover response")
    try:
        message = client.recv_records(timeout=3.0)
    except Exception as e:
        # This is fine if we are the handover selector
        if hs_sent:
            summary(
                "Client receive failed as expected since I'm the handover server: %s"
                % str(e))
        else:
            summary("Client receive failed: %s" % str(e))
        message = None
    if message is None:
        if hs_sent:
            summary(
                "No response received as expected since I'm the handover server"
            )
        else:
            summary("No response received")
        client.close()
        return
    summary("Received message: " + str(message))
    if len(message) < 1 or \
       not isinstance(message[0], ndef.HandoverSelectRecord):
        summary("Response was not Hs - received: " + message.type)
        client.close()
        return

    summary("Received handover select message")
    summary("alternative carriers: " + str(message[0].alternative_carriers))

    dpp_found = False
    for carrier in message:
        if isinstance(carrier, ndef.HandoverSelectRecord):
            continue
        summary("Remote carrier type: " + carrier.type)
        if carrier.type == "application/vnd.wfa.dpp":
            if len(carrier.data) == 0 or carrier.data[0] != 0:
                summary("URI Identifier Code 'None' not seen")
                continue
            summary("DPP carrier type match - send to wpa_supplicant")
            dpp_found = True
            uri = carrier.data[1:].decode("utf-8")
            summary("DPP URI: " + uri)
            res = wpas_report_handover_sel(uri)
            if res is None or "FAIL" in res:
                summary("DPP handover report rejected")
                break

            success_report("DPP handover reported successfully (initiator)")
            summary("peer_id=" + res)
            peer_id = int(res)
            wpas = wpas_connect()
            if wpas is None:
                break

            global enrollee_only
            global config_params
            if enrollee_only:
                extra = " role=enrollee"
            elif config_params:
                extra = " role=configurator " + config_params
            else:
                # TODO: Single Configurator instance
                res = wpas.request("DPP_CONFIGURATOR_ADD")
                if "FAIL" in res:
                    summary("Failed to initiate Configurator")
                    break
                conf_id = int(res)
                extra = " conf=sta-dpp configurator=%d" % conf_id
            global own_id
            summary("Initiate DPP authentication")
            cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id)
            cmd += extra
            res = wpas.request(cmd)
            if "FAIL" in res:
                summary("Failed to initiate DPP authentication")
            break

    if not dpp_found:
        summary(
            "DPP carrier not seen in response - allow peer to initiate a new handover with different parameters"
        )
        client.close()
        summary("Returning from dpp_handover_client")
        return

    summary("Remove peer")
    client.close()
    summary("Done with handover")
    global only_one
    if only_one:
        print("only_one -> stop loop")
        global continue_loop
        continue_loop = False

    global no_wait
    if no_wait:
        print("Trying to exit..")
        global terminate_now
        terminate_now = True

    summary("Returning from dpp_handover_client")
Example #9
0
    assert record.alternative_carriers[0].carrier_power_state == 'active'
    assert record.alternative_carriers[0].carrier_data_reference == 'wifi'
    assert record.alternative_carriers[0].auxiliary_data_reference[0] == 'a1'
    assert record.alternative_carriers[0].auxiliary_data_reference[1] == 'a2'
    assert record.alternative_carriers[1].carrier_power_state == 'inactive'
    assert record.alternative_carriers[1].carrier_data_reference == 'bt31'
    assert record.alternative_carriers[1].auxiliary_data_reference[0] == 'a3'
    assert len(record.unknown_records) == 1
    assert record.unknown_records[0].type == 'text/plain'
    assert record.unknown_records[0].name == 'txt'
    assert record.unknown_records[0].data == b'Hello'


handover_request_messages = [
    ('d102014872 11',
     [ndef.HandoverRequestRecord('1.1')]),
    ('91020a487211 d10204616301013100 5a030201612f62310001',
     [ndef.HandoverRequestRecord('1.1', None, (1, '1')),
      ndef.Record('a/b', '1', b'\x00\x01')]),
    ('d10208487212 d1020263721234',
     [ndef.HandoverRequestRecord('1.2', 0x1234)]),
    ('910211487212 91020263721234 510204616301013100 5a030201612f62310001',
     [ndef.HandoverRequestRecord('1.2', 0x1234, (1, '1')),
      ndef.Record('a/b', '1', b'\x00\x01')]),
    ('910211487212 91020263721234 510204616301013100 590205014863310203612f62',
     [ndef.HandoverRequestRecord('1.2', 0x1234, (1, '1')),
      ndef.HandoverCarrierRecord('a/b', None, '1')]),
]


class TestHandoverRequestMessage:
Example #10
0
def run_dpp_handover_client(handover, alt=False):
    chan_override = None
    if alt:
        chan_override = handover.altchanlist
        handover.alt_proposal_used = True
    global test_uri, test_alt_uri
    if test_uri:
        summary("TEST MODE: Using specified URI (alt=%s)" % str(alt))
        uri = test_alt_uri if alt else test_uri
    else:
        uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override)
    if uri is None:
        summary("Cannot start handover client - no bootstrap URI available",
                color=C_RED)
        return
    handover.my_uri = uri
    uri = ndef.UriRecord(uri)
    summary("NFC URI record for DPP: " + str(uri))
    carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data)
    global test_crn
    if test_crn:
        prev, = struct.unpack('>H', test_crn)
        summary("TEST MODE: Use specified crn %d" % prev)
        crn = test_crn
        test_crn = struct.pack('>H', prev + 0x10)
    else:
        crn = os.urandom(2)
    hr = ndef.HandoverRequestRecord(version="1.4", crn=crn)
    hr.add_alternative_carrier('active', carrier.name)
    message = [hr, carrier]
    summary("NFC Handover Request message for DPP: " + str(message))

    if handover.peer_crn is not None and not alt:
        summary("NFC handover request from peer was already received - do not send own")
        return
    if handover.client:
        summary("Use already started handover client")
        client = handover.client
    else:
        summary("Start handover client")
        client = HandoverClient(handover, handover.llc)
        try:
            summary("Trying to initiate NFC connection handover")
            client.connect()
            summary("Connected for handover")
        except nfc.llcp.ConnectRefused:
            summary("Handover connection refused")
            client.close()
            return
        except Exception as e:
            summary("Other exception: " + str(e))
            client.close()
            return
        handover.client = client

    if handover.peer_crn is not None and not alt:
        summary("NFC handover request from peer was already received - do not send own")
        return

    summary("Sending handover request")

    handover.my_crn_ready = True

    if not client.send_records(message):
        handover.my_crn_ready = False
        summary("Failed to send handover request", color=C_RED)
        run_client_alt(handover, alt)
        return

    handover.my_crn, = struct.unpack('>H', crn)

    summary("Receiving handover response")
    try:
        start = time.time()
        message = client.recv_records(timeout=3.0)
        end = time.time()
        summary("Received {} record(s) in {} seconds".format(len(message) if message is not None else -1, end - start))
    except Exception as e:
        # This is fine if we are the handover selector
        if handover.hs_sent:
            summary("Client receive failed as expected since I'm the handover server: %s" % str(e))
        elif handover.alt_proposal_used and not alt:
            summary("Client received failed for initial proposal as expected since alternative proposal was also used: %s" % str(e))
        else:
            summary("Client receive failed: %s" % str(e), color=C_RED)
        message = None
    if message is None:
        if handover.hs_sent:
            summary("No response received as expected since I'm the handover server")
        elif handover.alt_proposal_used and not alt:
            summary("No response received for initial proposal as expected since alternative proposal was also used")
        elif handover.try_own and not alt:
            summary("No response received for initial proposal as expected since alternative proposal will also be sent")
        else:
            summary("No response received", color=C_RED)
        run_client_alt(handover, alt)
        return
    summary("Received message: " + str(message))
    if len(message) < 1 or \
       not isinstance(message[0], ndef.HandoverSelectRecord):
        summary("Response was not Hs - received: " + message.type)
        return

    summary("Received handover select message")
    summary("alternative carriers: " + str(message[0].alternative_carriers))
    if handover.i_m_selector:
        summary("Ignore the received select since I'm the handover selector")
        run_client_alt(handover, alt)
        return

    if handover.alt_proposal_used and not alt:
        summary("Ignore received handover select for the initial proposal since alternative proposal was sent")
        client.close()
        return

    dpp_found = False
    for carrier in message:
        if isinstance(carrier, ndef.HandoverSelectRecord):
            continue
        summary("Remote carrier type: " + carrier.type)
        if carrier.type == "application/vnd.wfa.dpp":
            if len(carrier.data) == 0 or carrier.data[0] != 0:
                summary("URI Identifier Code 'None' not seen", color=C_RED)
                continue
            summary("DPP carrier type match - send to wpa_supplicant")
            dpp_found = True
            uri = carrier.data[1:].decode("utf-8")
            summary("DPP URI: " + uri)
            handover.peer_uri = uri
            if test_uri:
                summary("TEST MODE: Fake processing")
                break
            res = wpas_report_handover_sel(uri)
            if res is None or "FAIL" in res:
                summary("DPP handover report rejected", color=C_RED)
                break

            success_report("DPP handover reported successfully (initiator)")
            summary("peer_id=" + res)
            peer_id = int(res)
            wpas = wpas_connect()
            if wpas is None:
                break

            global enrollee_only
            global config_params
            if enrollee_only:
                extra = " role=enrollee"
            elif config_params:
                extra = " role=configurator " + config_params
            else:
                # TODO: Single Configurator instance
                res = wpas.request("DPP_CONFIGURATOR_ADD")
                if "FAIL" in res:
                    summary("Failed to initiate Configurator", color=C_RED)
                    break
                conf_id = int(res)
                extra = " conf=sta-dpp configurator=%d" % conf_id
            global own_id
            summary("Initiate DPP authentication")
            cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id)
            cmd += extra
            res = wpas.request(cmd)
            if "FAIL" in res:
                summary("Failed to initiate DPP authentication", color=C_RED)
            break

    if not dpp_found and handover.no_alt_proposal:
        summary("DPP carrier not seen in response - do not allow alternative proposal anymore")
    elif not dpp_found:
        summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters")
        handover.alt_proposal = True
        handover.my_crn_ready = False
        handover.my_crn = None
        handover.peer_crn = None
        handover.hs_sent = False
        summary("Returning from dpp_handover_client")
        return

    summary("Remove peer")
    handover.close()
    summary("Done with handover")
    global only_one
    if only_one:
        print("only_one -> stop loop")
        global continue_loop
        continue_loop = False

    global no_wait
    if no_wait or only_one:
        summary("Trying to exit..")
        global terminate_now
        terminate_now = True

    summary("Returning from dpp_handover_client")