Exemple #1
0
static int ah(const u8_t irk[16], const u8_t r[3], u8_t out[3])
{
	u8_t res[16];
	int err;

	BT_DBG("irk %s, r %s", bt_hex(irk, 16), bt_hex(r, 3));

	/* r' = padding || r */
	memcpy(res, r, 3);
	memset(res + 3, 0, 13);

	err = bt_encrypt_le(irk, res, res);
	if (err) {
		return err;
	}

	/* The output of the random address function ah is:
	 *      ah(h, r) = e(k, r') mod 2^24
	 * The output of the security function e is then truncated to 24 bits
	 * by taking the least significant 24 bits of the output of e as the
	 * result of ah.
	 */
	memcpy(out, res, 3);

	return 0;
}
Exemple #2
0
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
                           struct net_buf_simple *buf)
{
    u8_t flags = bt_mesh_net_flags(sub);
    struct bt_mesh_subnet_keys *keys;

    net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);

    if (sub->kr_flag) {
        keys = &sub->keys[1];
    } else {
        keys = &sub->keys[0];
    }

    net_buf_simple_add_u8(buf, flags);

    /* Network ID */
    net_buf_simple_add_mem(buf, keys->net_id, 8);

    /* IV Index */
    net_buf_simple_add_be32(buf, bt_mesh.iv_index);

    net_buf_simple_add_mem(buf, sub->auth, 8);

    BT_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx,
           flags, bt_hex(keys->net_id, 8));
    BT_DBG("IV Index 0x%08x Auth %s", bt_mesh.iv_index,
           bt_hex(sub->auth, 8));
}
Exemple #3
0
bool bt_rpa_irk_matches(const u8_t irk[16], const bt_addr_t *addr)
{
	u8_t hash[3];
	int err;

	BT_DBG("IRK %s bdaddr %s", bt_hex(irk, 16), bt_addr_str(addr));

	err = ah(irk, addr->val + 3, hash);
	if (err) {
		return false;
	}

	return !memcmp(addr->val, hash, 3);
}
Exemple #4
0
void bt_mesh_beacon_recv(struct net_buf_simple *buf)
{
    u8_t type;

    BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));

    if (buf->len < 1) {
        BT_ERR("Too short beacon");
        return;
    }

    type = net_buf_simple_pull_u8(buf);
    switch (type) {
        case BEACON_TYPE_UNPROVISIONED:
            BT_DBG("Ignoring unprovisioned device beacon");
            break;
        case BEACON_TYPE_SECURE:
            secure_beacon_recv(buf);
            break;
        default:
            BT_WARN("Unknown beacon type 0x%02x", type);
            break;
    }
}
Exemple #5
0
static inline void read_payload(void)
{
	struct net_buf *buf;
	bool prio;
	int read;

	if (!rx.buf) {
		rx.buf = get_rx(K_NO_WAIT);
		if (!rx.buf) {
			if (rx.discardable) {
				BT_WARN("Discarding event 0x%02x", rx.evt.evt);
				rx.discard = rx.remaining;
				reset_rx();
				return;
			}

			BT_WARN("Failed to allocate, deferring to rx_thread");
			uart_irq_rx_disable(h4_dev);
			return;
		}

		BT_DBG("Allocated rx.buf %p", rx.buf);

		if (rx.remaining > net_buf_tailroom(rx.buf)) {
			BT_ERR("Not enough space in buffer");
			rx.discard = rx.remaining;
			reset_rx();
			return;
		}

		copy_hdr(rx.buf);
	}

	read = uart_fifo_read(h4_dev, net_buf_tail(rx.buf), rx.remaining);
	net_buf_add(rx.buf, read);
	rx.remaining -= read;

	BT_DBG("got %d bytes, remaining %u", read, rx.remaining);
	BT_DBG("Payload (len %u): %s", rx.buf->len,
	       bt_hex(rx.buf->data, rx.buf->len));

	if (rx.remaining) {
		return;
	}

	prio = (rx.type == H4_EVT && bt_hci_evt_is_prio(rx.evt.evt));

	buf = rx.buf;
	rx.buf = NULL;

	if (rx.type == H4_EVT) {
		bt_buf_set_type(buf, BT_BUF_EVT);
	} else {
		bt_buf_set_type(buf, BT_BUF_ACL_IN);
	}

	reset_rx();

	if (prio) {
		BT_DBG("Calling bt_recv_prio(%p)", buf);
		bt_recv_prio(buf);
	} else {
		BT_DBG("Putting buf %p to rx fifo", buf);
		net_buf_put(&rx.fifo, buf);
	}
}
Exemple #6
0
static void secure_beacon_recv(struct net_buf_simple *buf)
{
    u8_t *data, *net_id, *auth;
    struct bt_mesh_subnet *sub;
    u32_t iv_index;
    bool new_key, kr_change, iv_change;
    u8_t flags;

    if (buf->len < 21) {
        BT_ERR("Too short secure beacon (len %u)", buf->len);
        return;
    }

    sub = cache_check(buf->data);
    if (sub) {
        /* We've seen this beacon before - just update the stats */
        goto update_stats;
    }

    /* So we can add to the cache if auth matches */
    data = buf->data;

    flags = net_buf_simple_pull_u8(buf);
    net_id = buf->data;
    net_buf_simple_pull(buf, 8);
    iv_index = net_buf_simple_pull_be32(buf);
    auth = buf->data;

    BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
           flags, bt_hex(net_id, 8), iv_index);

    sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
    if (!sub) {
        BT_DBG("No subnet that matched beacon");
        return;
    }

    if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
        BT_WARN("Ignoring Phase 2 KR Update secured using old key");
        return;
    }

    cache_add(data, sub);

    /* If we have NetKey0 accept initiation only from it */
    if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
        sub->net_idx != BT_MESH_KEY_PRIMARY) {
        BT_WARN("Ignoring secure beacon on non-primary subnet");
        goto update_stats;
    }

    BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
           sub->net_idx, iv_index, bt_mesh.iv_index);

    if (bt_mesh.ivu_initiator &&
        bt_mesh.iv_update == BT_MESH_IV_UPDATE(flags)) {
        bt_mesh_beacon_ivu_initiator(false);
    }

    iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));

    kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
    if (kr_change) {
        bt_mesh_net_beacon_update(sub);
    }

    if (iv_change) {
        /* Update all subnets */
        bt_mesh_net_sec_update(NULL);
    } else if (kr_change) {
        /* Key Refresh without IV Update only impacts one subnet */
        bt_mesh_net_sec_update(sub);
    }

update_stats:
    if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
        sub->beacons_cur < 0xff) {
        sub->beacons_cur++;
    }
}