예제 #1
0
파일: util.py 프로젝트: sybohy/bellows
def zha_security(controller=False):
    empty_key_data = t.EmberKeyData()
    empty_key_data.contents = t.fixed_list(16, t.uint8_t)([t.uint8_t(0)] * 16)
    zha_key = t.EmberKeyData()
    zha_key.contents = t.fixed_list(
        16, t.uint8_t)([t.uint8_t(c) for c in b"ZigBeeAlliance09"])

    isc = t.EmberInitialSecurityState()
    isc.bitmask = t.uint16_t(
        t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
        | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY)
    isc.preconfiguredKey = zha_key
    isc.networkKey = empty_key_data
    isc.networkKeySequenceNumber = t.uint8_t(0)
    isc.preconfiguredTrustCenterEui64 = t.EmberEUI64([t.uint8_t(0)] * 8)

    if controller:
        isc.bitmask |= (
            t.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY
            | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY)
        isc.bitmask = t.uint16_t(isc.bitmask)
        random_key = t.fixed_list(
            16, t.uint8_t)([t.uint8_t(x) for x in os.urandom(16)])
        isc.networkKey = random_key
    return isc
예제 #2
0
def zha_security(config: Dict[str, Any], controller: bool = False) -> None:

    isc = t.EmberInitialSecurityState()
    isc.bitmask = t.uint16_t(
        t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
        | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY)
    isc.preconfiguredKey = t.EmberKeyData(
        config[zigpy.config.CONF_NWK_TC_LINK_KEY])
    nwk_key = config[zigpy.config.CONF_NWK_KEY]
    if nwk_key is None:
        nwk_key = os.urandom(16)
    isc.networkKey = t.EmberKeyData(nwk_key)
    isc.networkKeySequenceNumber = t.uint8_t(
        config[zigpy.config.CONF_NWK_KEY_SEQ])
    tc_addr = config[zigpy.config.CONF_NWK_TC_ADDRESS]
    if tc_addr is None:
        tc_addr = [0x00] * 8
    isc.preconfiguredTrustCenterEui64 = t.EmberEUI64(tc_addr)

    if controller:
        isc.bitmask |= (
            t.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY
            | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY)
        isc.bitmask = t.uint16_t(isc.bitmask)
    return isc
예제 #3
0
    async def permit_with_key(self, node, code, time_s=60):
        if type(node) is not t.EmberEUI64:
            node = t.EmberEUI64([t.uint8_t(p) for p in node])

        key = zigpy.util.convert_install_code(code)
        if key is None:
            raise Exception("Invalid install code")

        link_key = t.EmberKeyData()
        link_key.contents = key
        v = await self._ezsp.addTransientLinkKey(node, link_key)

        if v[0] != t.EmberStatus.SUCCESS:
            raise Exception("Failed to set link key")

        v = await self._ezsp.setPolicy(
            t.EzspPolicyId.TC_KEY_REQUEST_POLICY,
            t.EzspDecisionId.GENERATE_NEW_TC_LINK_KEY,
        )
        if v[0] != t.EmberStatus.SUCCESS:
            raise Exception(
                "Failed to change policy to allow generation of new trust center keys"
            )

        return await self.permit(time_s)
예제 #4
0
async def join_with_code(app, listener, ieee, cmd, data, service):

    code = b"\xA8\x16\x92\x7F\xB1\x9B\x78\x55\xC1\xD7\x76\x0D\x5C\xAD\x63\x7F\x69\xCC"
    # res = await app.permit_with_key(node, code, 60)
    import bellows.types as bt

    node = t.EUI64.convert("04:cf:8c:df:3c:75:e1:e7")
    link_key = bt.EmberKeyData(b"ZigBeeAlliance09")
    res = await app._ezsp.addTransientLinkKey(node, link_key)
    LOGGER.debug("permit with key: %s", res)
    res = await app.permit(60)
예제 #5
0
파일: util.py 프로젝트: titilambert/bellows
def aes_mmo_hash(data):
    result_len = 0
    remaining_length = 0
    length = len(data)
    result = bytearray([0] * AES.block_size)
    temp = bytearray([0] * AES.block_size)

    if (data and length > 0):
        remaining_length = length & (AES.block_size - 1)
        if (length >= AES.block_size):
            # Mask out the lower byte since hash update will hash
            # everything except the last piece, if the last piece
            # is less than 16 bytes.
            hashed_length = (length & ~(AES.block_size - 1))
            (result_len, result) = aes_mmo_hash_update(result_len, result,
                                                       data)
            data = data[hashed_length:]

    for i in range(remaining_length):
        temp[i] = data[i]

    # Per the spec, Concatenate a 1 bit followed by all zero bits
    # (previous memset() on temp[] set the rest of the bits to zero)
    temp[remaining_length] = 0x80
    result_len += remaining_length

    # If appending the bit string will push us beyond the 16-byte boundary
    # we must hash that block and append another 16-byte block.
    if ((AES.block_size - remaining_length) < 3):
        (result_len, result) = aes_mmo_hash_update(result_len, result, temp)

        # Since this extra data is due to the concatenation,
        # we remove that length. We want the length of data only
        # and not the padding.
        result_len -= AES.block_size
        temp = bytearray([0] * AES.block_size)

    bit_size = result_len * 8
    temp[AES.block_size - 2] = (bit_size >> 8) & 0xFF
    temp[AES.block_size - 1] = (bit_size) & 0xFF

    (result_len, result) = aes_mmo_hash_update(result_len, result, temp)

    key = t.EmberKeyData()
    key.contents = t.fixed_list(16, t.uint8_t)([t.uint8_t(c) for c in result])
    return key
예제 #6
0
async def join_with_code(
    app, listener, ieee, cmd, data, service, event_data, params
):
    import bellows.types as bt

    node = ieee  # Was: t.EUI64.convert("04:cf:8c:df:3c:75:e1:e7")

    # Original code:
    #
    # code = (
    #   b"\xA8\x16\x92\x7F\xB1\x9B\x78\x55\xC1"
    #    + b"\xD7\x76\x0D\x5C\xAD\x63\x7F\x69\xCC"
    # )
    code = params[p.CODE]
    res = await app.permit_with_key(node, code, 60)
    link_key = bt.EmberKeyData(b"ZigBeeAlliance09")
    res = await app._ezsp.addTransientLinkKey(node, link_key)
    LOGGER.debug("permit with key: %s", res)
    res = await app.permit(60)
예제 #7
0
    async def permit_with_key(self, node, code, time_s=60):
        if type(node) is not t.EmberEUI64:
            node = t.EmberEUI64([t.uint8_t(p) for p in node])

        key = zigpy.util.convert_install_code(code)
        if key is None:
            raise Exception("Invalid install code")

        link_key = t.EmberKeyData(key)
        v = await self._ezsp.addTransientLinkKey(node, link_key)

        if v[0] != t.EmberStatus.SUCCESS:
            raise Exception("Failed to set link key")

        if self._ezsp.ezsp_version >= 8:
            mask_type = self._ezsp.types.EzspDecisionBitmask.ALLOW_JOINS
            bitmask = mask_type.ALLOW_JOINS | mask_type.JOINS_USE_INSTALL_CODE_KEY
            await self._ezsp.setPolicy(
                self._ezsp.types.EzspPolicyId.TRUST_CENTER_POLICY, bitmask)

        return await super().permit(time_s)
예제 #8
0
파일: backup.py 프로젝트: Yoda-x/bellows
async def _restore(ezsp,
                   backup_data,
                   force,
                   update_eui64_token=False,
                   upg_tc_link_key=False):
    """Restore backup."""

    (status, ) = await ezsp.networkInit()
    LOGGER.debug("Network init status: %s", status)
    assert status in (t.EmberStatus.SUCCESS, t.EmberStatus.NOT_JOINED)

    if status == t.EmberStatus.SUCCESS:
        if not force:
            click.echo("Network is up, not forcing restore")
            return
        try:
            (status, ) = await ezsp.leaveNetwork()
            if status != t.EmberStatus.NETWORK_DOWN:
                LOGGER.error("Couldn't leave network")
                return
        except asyncio.TimeoutError:
            LOGGER.error("Didn't not receive stack changed status callback")
            return

    if update_eui64_token:
        ncp_eui64 = t.EmberEUI64(backup_data[ATTR_NODE_EUI64]).serialize()
        (status, ) = await ezsp.setMfgToken(t.EzspMfgTokenId.MFG_CUSTOM_EUI_64,
                                            ncp_eui64)

    sec_bitmask = (t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY
                   | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY
                   | t.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY
                   | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY
                   | t.EmberInitialSecurityBitmask.NO_FRAME_COUNTER_RESET)
    if not is_well_known_key(backup_data[ATTR_KEY_GLOBAL][ATTR_KEY]):
        sec_bitmask |= t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY

    init_sec_state = t.EmberInitialSecurityState(
        bitmask=sec_bitmask,
        preconfiguredKey=backup_data[ATTR_KEY_GLOBAL][ATTR_KEY],
        networkKey=backup_data[ATTR_KEY_NWK][ATTR_KEY],
        networkKeySequenceNumber=backup_data[ATTR_KEY_NWK][ATTR_KEY_SEQ],
        preconfiguredTrustCenterEui64=[0x00] * 8,
    )
    if (upg_tc_link_key
            and t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY
            not in sec_bitmask):
        init_sec_state.bitmask |= (
            t.EmberInitialSecurityBitmask.TRUST_CENTER_USES_HASHED_LINK_KEY)
        init_sec_state.preconfiguredKey = t.EmberKeyData(os.urandom(16))

    (status, ) = await ezsp.setInitialSecurityState(init_sec_state)
    LOGGER.debug("Set initial security state: %s", status)
    assert status == t.EmberStatus.SUCCESS

    if backup_data[ATTR_KEY_TABLE]:
        await _restore_keys(ezsp, backup_data[ATTR_KEY_TABLE])

    network_key = backup_data[ATTR_KEY_NWK]
    (status, ) = await ezsp.setValue(
        ezsp.types.EzspValueId.VALUE_NWK_FRAME_COUNTER,
        t.uint32_t(network_key[ATTR_KEY_FRAME_COUNTER_OUT]).serialize(),
    )
    LOGGER.debug("Set network frame counter: %s", status)
    assert status == t.EmberStatus.SUCCESS

    tc_key = backup_data[ATTR_KEY_GLOBAL]
    (status, ) = await ezsp.setValue(
        ezsp.types.EzspValueId.VALUE_APS_FRAME_COUNTER,
        t.uint32_t(tc_key[ATTR_KEY_FRAME_COUNTER_OUT]).serialize(),
    )
    LOGGER.debug("Set network frame counter: %s", status)
    assert status == t.EmberStatus.SUCCESS

    await _form_network(ezsp, backup_data)
    await asyncio.sleep(2)