Initial cut of LL privacy
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/7327c542 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/7327c542 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/7327c542 Branch: refs/heads/develop Commit: 7327c542d000b1323c669bba791da45fd87139b3 Parents: 6e95f44 Author: William San Filippo <wi...@runtime.io> Authored: Wed May 18 14:06:01 2016 -0700 Committer: Paul Dietrich <paulfdietr...@yahoo.com> Committed: Thu Jun 2 12:53:52 2016 -0700 ---------------------------------------------------------------------- .../controller/include/controller/ble_hw.h | 35 +- .../controller/include/controller/ble_ll.h | 1 + .../include/controller/ble_ll_resolv.h | 79 ++++ .../controller/include/controller/ble_phy.h | 6 + net/nimble/controller/src/ble_ll.c | 29 +- net/nimble/controller/src/ble_ll_adv.c | 255 +++++++------ net/nimble/controller/src/ble_ll_conn.c | 34 +- net/nimble/controller/src/ble_ll_conn_priv.h | 3 +- net/nimble/controller/src/ble_ll_ctrl.c | 2 +- net/nimble/controller/src/ble_ll_hci.c | 27 ++ net/nimble/controller/src/ble_ll_rand.c | 26 ++ net/nimble/controller/src/ble_ll_resolv.c | 378 +++++++++++++++++++ net/nimble/controller/src/ble_ll_scan.c | 2 + net/nimble/drivers/nrf51/src/ble_hw.c | 195 ++++++++-- net/nimble/drivers/nrf51/src/ble_phy.c | 107 +++++- net/nimble/drivers/nrf52/src/ble_hw.c | 116 +++++- net/nimble/drivers/nrf52/src/ble_phy.c | 85 ++++- net/nimble/host/src/host_hci_cmd.c | 4 +- net/nimble/include/nimble/ble.h | 6 +- net/nimble/include/nimble/hci_common.h | 2 +- net/nimble/include/nimble/nimble_opt.h | 7 +- 21 files changed, 1189 insertions(+), 210 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/include/controller/ble_hw.h ---------------------------------------------------------------------- diff --git a/net/nimble/controller/include/controller/ble_hw.h b/net/nimble/controller/include/controller/ble_hw.h index 6166e58..da425de 100644 --- a/net/nimble/controller/include/controller/ble_hw.h +++ b/net/nimble/controller/include/controller/ble_hw.h @@ -6,7 +6,7 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, @@ -57,23 +57,44 @@ int ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias); /** * Start the random number generator - * - * @return int + * + * @return int */ int ble_hw_rng_start(void); /** * Stop the random generator - * - * @return int + * + * @return int */ int ble_hw_rng_stop(void); /** * Read the random number generator. - * - * @return uint8_t + * + * @return uint8_t */ uint8_t ble_hw_rng_read(void); +/* Clear the resolving list*/ +void ble_hw_resolv_list_clear(void); + +/* Add a device to the hw resolving list */ +int ble_hw_resolv_list_add(uint8_t *irk); + +/* Remove a device from the hw resolving list */ +void ble_hw_resolv_list_rmv(int index); + +/* Returns the size of the whitelist in HW */ +uint8_t ble_hw_resolv_list_size(void); + +/* Enable the resolving list */ +void ble_hw_resolv_list_enable(void); + +/* Disables resolving list devices */ +void ble_hw_resolv_list_disable(void); + +/* Returns index of resolved address; -1 if not resolved */ +int ble_hw_resolv_list_match(void); + #endif /* H_BLE_HW_ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/include/controller/ble_ll.h ---------------------------------------------------------------------- diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h index 8c8cb54..9a4014c 100644 --- a/net/nimble/controller/include/controller/ble_ll.h +++ b/net/nimble/controller/include/controller/ble_ll.h @@ -354,6 +354,7 @@ int ble_ll_chk_txrx_time(uint16_t time); int ble_ll_rand_init(void); void ble_ll_rand_sample(uint8_t rnum); int ble_ll_rand_data_get(uint8_t *buf, uint8_t len); +void ble_ll_rand_prand_get(uint8_t *prand); int ble_ll_rand_start(void); /* http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/include/controller/ble_ll_resolv.h ---------------------------------------------------------------------- diff --git a/net/nimble/controller/include/controller/ble_ll_resolv.h b/net/nimble/controller/include/controller/ble_ll_resolv.h new file mode 100644 index 0000000..bddf70b --- /dev/null +++ b/net/nimble/controller/include/controller/ble_ll_resolv.h @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_RESOLV_ +#define H_BLE_LL_RESOLV_ + +/* + * An entry in the resolving list. + * The identity address is stored in little endian format. + * The IRKs are stored in big endian format. + */ +struct ble_ll_resolv_entry +{ + uint8_t rl_valid; + uint8_t rl_addr_type; + uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; + uint8_t rl_local_irk[16]; + uint8_t rl_peer_irk[16]; +}; + +extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[]; + +/* Clear the resolving list */ +int ble_ll_resolv_list_clr(void); + +/* Read the size of the resolving list */ +int ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen); + +/* Add a device to the resolving list */ +int ble_ll_resolv_list_add(uint8_t *cmdbuf); + +/* Remove a device from the resolving list */ +int ble_ll_resolv_list_rmv(uint8_t *cmdbuf); + +/* Address resolution enable command */ +int ble_ll_resolv_enable_cmd(uint8_t *cmdbuf); + +int ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf); +void ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf); + +/* Enable resolving list */ +void ble_ll_resolv_list_enable(void); + +/* Disable resolving list */ +void ble_ll_resolv_list_disable(void); + +/* Finds 'addr' in resolving list. */ +struct ble_ll_resolv_entry * +ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type); + +/* Called to determine if the IRK is all zero. */ +int ble_ll_resolv_irk_nonzero(uint8_t *irk); + +/* Returns true if address resolution is enabled */ +uint8_t ble_ll_resolv_enabled(void); + +/* Reset private address resolution */ +void ble_ll_resolv_list_reset(void); + +void ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local, + uint8_t *addr); + +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/include/controller/ble_phy.h ---------------------------------------------------------------------- diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h index edbfd89..1333c19 100644 --- a/net/nimble/controller/include/controller/ble_phy.h +++ b/net/nimble/controller/include/controller/ble_phy.h @@ -139,4 +139,10 @@ void ble_phy_encrypt_disable(void); /* Set the packet counters and dir used by LE encyption */ void ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir); +/* Enable phy resolving list */ +void ble_phy_resolv_list_enable(void); + +/* Disable phy resolving list */ +void ble_phy_resolv_list_disable(void); + #endif /* H_BLE_PHY_ */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c index 7ff290d..e53d56f 100644 --- a/net/nimble/controller/src/ble_ll.c +++ b/net/nimble/controller/src/ble_ll.c @@ -33,6 +33,8 @@ #include "controller/ble_ll_sched.h" #include "controller/ble_ll_scan.h" #include "controller/ble_ll_hci.h" +#include "controller/ble_ll_whitelist.h" +#include "controller/ble_ll_resolv.h" #include "ble_ll_conn_priv.h" #include "hal/hal_cputime.h" @@ -286,11 +288,26 @@ ble_ll_chk_txrx_time(uint16_t time) return rc; } +/* WWW: check where called to see if correct */ +/** + * Checks to see if the address is a resolvable private address. Th + * + * + * @param addr + * + * @return int + */ int ble_ll_is_resolvable_priv_addr(uint8_t *addr) { - /* XXX: implement this */ - return 0; + int rc; + + if ((addr[5] & 0xc0) == 0x40) { + rc = 1; + } else { + rc = 0; + } + return rc; } /* Checks to see that the device is a valid random address */ @@ -1065,6 +1082,14 @@ ble_ll_reset(void) /* Reset our random address */ memset(g_random_addr, 0, BLE_DEV_ADDR_LEN); + /* Clear the whitelist */ + ble_ll_whitelist_clear(); + + /* Reset resolving list */ +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + ble_ll_resolv_list_reset(); +#endif + /* Re-initialize the PHY */ rc = ble_phy_init(); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_adv.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c index 8a1e8e6..c49686c 100644 --- a/net/nimble/controller/src/ble_ll_adv.c +++ b/net/nimble/controller/src/ble_ll_adv.c @@ -26,11 +26,13 @@ #include "nimble/nimble_opt.h" #include "nimble/hci_common.h" #include "controller/ble_phy.h" +#include "controller/ble_hw.h" #include "controller/ble_ll.h" #include "controller/ble_ll_adv.h" #include "controller/ble_ll_sched.h" #include "controller/ble_ll_scan.h" #include "controller/ble_ll_whitelist.h" +#include "controller/ble_ll_resolv.h" #include "ble_ll_conn_priv.h" #include "hal/hal_cputime.h" #include "hal/hal_gpio.h" @@ -39,7 +41,6 @@ * 1) Need to look at advertising and scan request PDUs. Do I allocate these * once? Do I use a different pool for smaller ones? Do I statically declare * them? - * 2) Only public device addresses supported right now. * 3) How do features get supported? What happens if device does not support * advertising? (for example) * 4) How to determine the advertising interval we will actually use. As of @@ -69,16 +70,19 @@ struct ble_ll_adv_sm uint8_t adv_chan; uint8_t scan_rsp_len; uint8_t adv_pdu_len; + int8_t adv_rpa_index; uint16_t adv_itvl_min; uint16_t adv_itvl_max; uint32_t adv_itvl_usecs; uint32_t adv_event_start_time; uint32_t adv_pdu_start_time; uint32_t adv_dir_hd_end_time; + uint8_t adva[BLE_DEV_ADDR_LEN]; + uint8_t adv_rpa[BLE_DEV_ADDR_LEN]; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; uint8_t initiator_addr[BLE_DEV_ADDR_LEN]; uint8_t adv_data[BLE_ADV_DATA_MAX_LEN]; uint8_t scan_rsp_data[BLE_SCAN_RSP_DATA_MAX_LEN]; - struct os_mbuf *scan_rsp_pdu; struct os_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; }; @@ -130,36 +134,6 @@ ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm) } /** - * Compares the advertiser address in an advertising PDU (scan request or - * connect request) with our address to see if there is a match - * - * @param rxbuf Pointer to received PDU - * - * @return int Returns memcmp return values (0 = match). - */ -static int -ble_ll_adv_addr_cmp(uint8_t *rxbuf) -{ - int rc; - uint8_t *adva; - uint8_t *our_addr; - uint8_t rxaddr_type; - - /* Determine if this is addressed to us */ - rxaddr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK; - if (rxaddr_type) { - our_addr = g_random_addr; - } else { - our_addr = g_dev_addr; - } - - adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; - rc = memcmp(our_addr, adva, BLE_DEV_ADDR_LEN); - - return rc; -} - -/** * Create the advertising PDU * * @param advsm Pointer to advertisement state machine @@ -172,7 +146,6 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) uint8_t *dptr; uint8_t pdulen; uint8_t pdu_type; - uint8_t *addr; /* assume this is not a direct ind */ adv_data_len = advsm->adv_len; @@ -219,16 +192,9 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) /* Set the PDU length in the state machine (includes header) */ advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN; - /* Construct scan response */ - if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_PUBLIC) { - addr = g_dev_addr; - } else if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { + /* Set TxAdd to random if needed */ + if (advsm->own_addr_type & 1) { pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - addr = g_random_addr; - } else { - /* XXX: unsupported for now. Should never happen */ - addr = NULL; - assert(0); } /* Get the advertising PDU and initialize it*/ @@ -236,7 +202,7 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) /* Construct advertisement */ dptr = m->om_data; - memcpy(dptr, addr, BLE_DEV_ADDR_LEN); + memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); dptr += BLE_DEV_ADDR_LEN; /* For ADV_DIRECT_IND, we need to put initiators address in there */ @@ -255,52 +221,42 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m) * * @param advsm */ -static void +static struct os_mbuf * ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm) { uint8_t scan_rsp_len; uint8_t *dptr; - uint8_t *addr; uint8_t pdulen; uint8_t hdr; struct os_mbuf *m; + /* Obtain scan response buffer */ + m = os_msys_get_pkthdr(BLE_MBUF_PAYLOAD_SIZE, sizeof(struct ble_mbuf_hdr)); + if (!m) { + return NULL; + } + /* Make sure that the length is valid */ scan_rsp_len = advsm->scan_rsp_len; assert(scan_rsp_len <= BLE_SCAN_RSP_DATA_MAX_LEN); - /* Set PDU payload length */ + /* Set BLE transmit header */ pdulen = BLE_DEV_ADDR_LEN + scan_rsp_len; - - /* Get the advertising PDU */ - m = advsm->scan_rsp_pdu; - assert(m != NULL); - - /* Construct scan response */ - if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_PUBLIC) { - hdr = BLE_ADV_PDU_TYPE_SCAN_RSP; - addr = g_dev_addr; - } else if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) { - hdr = BLE_ADV_PDU_TYPE_SCAN_RSP | BLE_ADV_PDU_HDR_TXADD_RAND; - addr = g_random_addr; - } else { - /* XXX: unsupported for now */ - hdr = 0; - addr = NULL; - assert(0); + hdr = BLE_ADV_PDU_TYPE_SCAN_RSP; + if (advsm->own_addr_type & 1) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; } - /* Set BLE transmit header */ ble_ll_mbuf_init(m, pdulen, hdr); - /* Put our address into buffer */ + /* Construct scan response */ dptr = m->om_data; - memcpy(dptr, addr, BLE_DEV_ADDR_LEN); - - /* Copy in scan response data, if any */ + memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN); if (scan_rsp_len != 0) { memcpy(dptr + BLE_DEV_ADDR_LEN, advsm->scan_rsp_data, scan_rsp_len); } + + return m; } /** @@ -363,6 +319,15 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) ble_phy_encrypt_disable(); #endif +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + advsm->adv_rpa_index = 0; + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + /* Set phy mode based on type of advertisement */ if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { end_trans = BLE_PHY_TRANSITION_NONE; @@ -552,13 +517,17 @@ ble_ll_adv_set_adv_params(uint8_t *cmd) return BLE_ERR_INV_HCI_CMD_PARMS; } - /* - * XXX: return unsupported feature if own is address is not public or - * static random as we have not implemented non-static random addresses. - */ +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + /* Copy peer address */ + memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN); + } +#else + /* If we dont support privacy these own address types wont work */ if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { return BLE_ERR_UNSUPPORTED; } +#endif /* There are only three adv channels, so check for any outside the range */ adv_chanmask = cmd[13]; @@ -628,6 +597,8 @@ static int ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) { uint8_t adv_chan; + uint8_t *addr; + struct ble_ll_resolv_entry *rl; /* * This is not in the specification. I will reject the command with a @@ -642,9 +613,35 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) } } + /* Set advertising address */ + if ((advsm->own_addr_type & 1) == 0) { + addr = g_dev_addr; + } else { + addr = g_random_addr; + } + memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN); + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + /* WWW: + * 1) Make sure we are doing this for the proper adv types + */ + if (ble_ll_resolv_enabled()) { + if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + rl = ble_ll_resolv_list_find(advsm->peer_addr, advsm->peer_addr_type); + if (rl && ble_ll_resolv_irk_nonzero(rl->rl_local_irk)) { + ble_ll_resolv_gen_priv_addr(rl, 1, advsm->adva); + } + } + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + /* Set flag telling us that advertising is enabled */ advsm->enabled = 1; + /* WWW: what about privacy for direct? */ /* Determine the advertising interval we will use */ if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) { /* Set it to max. allowed for high duty cycle advertising */ @@ -654,11 +651,6 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) advsm->adv_itvl_usecs *= BLE_LL_ADV_ITVL; } - /* Create scan response PDU (if needed) */ - if (advsm->adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { - ble_ll_adv_scan_rsp_pdu_make(advsm); - } - /* Set first advertising channel */ adv_chan = ble_ll_adv_first_chan(advsm); advsm->adv_chan = adv_chan; @@ -758,7 +750,6 @@ int ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t len) { uint8_t datalen; - os_sr_t sr; struct ble_ll_adv_sm *advsm; /* Check for valid scan response data length */ @@ -772,15 +763,6 @@ ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t len) advsm->scan_rsp_len = datalen; memcpy(advsm->scan_rsp_data, cmd + 1, datalen); - /* Re-make the scan response PDU since data may have changed */ - OS_ENTER_CRITICAL(sr); - /* - * XXX: there is a chance, even with interrupts disabled, that - * we are transmitting the scan response PDU while writing to it. - */ - ble_ll_adv_scan_rsp_pdu_make(advsm); - OS_EXIT_CRITICAL(sr); - return 0; } @@ -828,27 +810,53 @@ static int ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) { int rc; + int index; uint8_t chk_whitelist; uint8_t txadd; uint8_t *rxbuf; + uint8_t *adva; struct ble_mbuf_hdr *ble_hdr; struct ble_ll_adv_sm *advsm; + struct os_mbuf *scan_rsp; + /* See if adva in the request (scan or connect) matches what we sent */ + advsm = &g_ble_ll_adv_sm; rxbuf = rxpdu->om_data; - if (ble_ll_adv_addr_cmp(rxbuf)) { + adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; + if (memcmp(advsm->adva, adva, BLE_DEV_ADDR_LEN)) { return -1; } /* Set device match bit if we are whitelisting */ - advsm = &g_ble_ll_adv_sm; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { chk_whitelist = advsm->adv_filter_policy & 1; } else { chk_whitelist = advsm->adv_filter_policy & 2; } - /* Set device match bit if we are whitelisting */ ble_hdr = BLE_MBUF_HDR_PTR(rxpdu); + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + uint8_t *peer; + + peer = rxbuf + BLE_LL_PDU_HDR_LEN; + if (ble_ll_is_resolvable_priv_addr(peer) && ble_ll_resolv_enabled()) { + index = ble_hw_resolv_list_match(); + if (index >= 0) { + advsm->adv_rpa_index = index; + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; + if (chk_whitelist) { + chk_whitelist = 0; + } + } else { + if (chk_whitelist) { + return -1; + } + } + } +#endif + + /* Set device match bit if we are whitelisting */ if (chk_whitelist) { /* Get the scanners address type */ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { @@ -861,17 +869,25 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, txadd)) { return -1; } - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; } + /* + * We set the device match bit to tell the upper layer that we will + * accept the request + */ + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; + /* Setup to transmit the scan response if appropriate */ rc = -1; if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) { - ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm); - rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_NONE); - if (!rc) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; - STATS_INC(ble_ll_stats, scan_rsp_txg); + scan_rsp = ble_ll_adv_scan_rsp_pdu_make(advsm); + if (scan_rsp) { + ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm); + rc = ble_phy_tx(scan_rsp, BLE_PHY_TRANSITION_NONE); + if (!rc) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD; + STATS_INC(ble_ll_stats, scan_rsp_txg); + } } } @@ -893,6 +909,7 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) { int valid; uint8_t pyld_len; + uint8_t resolved; uint8_t *inita; uint32_t endtime; struct ble_ll_adv_sm *advsm; @@ -900,14 +917,10 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) /* Check filter policy. */ valid = 0; advsm = &g_ble_ll_adv_sm; - if (advsm->adv_filter_policy & 2) { - if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { - /* valid connection request received */ - valid = 1; - } - } else { - /* If this is for us? */ - if (!ble_ll_adv_addr_cmp(rxbuf)) { + inita = rxbuf + BLE_LL_PDU_HDR_LEN; + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) { + valid = 1; + if ((advsm->adv_filter_policy & 2) == 0) { /* * Only accept connect requests from the desired address if we * are doing directed advertising @@ -915,22 +928,36 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) || (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) { /* XXX: not sure if this works if address is random */ + /* WWW: deal with RPA */ /* Compare addresses */ - inita = rxbuf + BLE_LL_PDU_HDR_LEN; - if (!memcmp(advsm->initiator_addr, inita, BLE_DEV_ADDR_LEN)) { - valid = 1; + if (memcmp(advsm->initiator_addr, inita, BLE_DEV_ADDR_LEN)) { + valid = 0; } - } else { - valid = 1; } } } if (valid) { + resolved = BLE_MBUF_HDR_RESOLVED(hdr); +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + if (resolved) { + /* Retain the resolvable private address that we received. */ + memcpy(advsm->adv_rpa, inita, BLE_DEV_ADDR_LEN); + + /* + * Overwrite received inita with identity address since that + * is used from now on. + */ + memcpy(inita, + g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr, + BLE_DEV_ADDR_LEN); + } +#endif + /* Try to start slave connection. If successful, stop advertising */ pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK; endtime = hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len); - valid = ble_ll_conn_slave_start(rxbuf, endtime); + valid = ble_ll_conn_slave_start(rxbuf, endtime, resolved); if (valid) { ble_ll_adv_sm_stop(advsm); } @@ -1251,9 +1278,6 @@ ble_ll_adv_reset(void) /* Stop advertising state machine */ ble_ll_adv_sm_stop(advsm); - /* Free scan pdu's */ - os_mbuf_free_chain(advsm->scan_rsp_pdu); - /* re-initialize the advertiser state machine */ ble_ll_adv_init(); } @@ -1285,10 +1309,5 @@ ble_ll_adv_init(void) /* Initialize advertising tx done event */ advsm->adv_txdone_ev.ev_type = BLE_LL_EVENT_ADV_EV_DONE; advsm->adv_txdone_ev.ev_arg = advsm; - - /* Get a scan response mbuf (packet header) and attach to state machine */ - advsm->scan_rsp_pdu = os_msys_get_pkthdr(BLE_MBUF_PAYLOAD_SIZE, - sizeof(struct ble_mbuf_hdr)); - assert(advsm->scan_rsp_pdu != NULL); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_conn.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c index e42f589..fe72a8e 100644 --- a/net/nimble/controller/src/ble_ll_conn.c +++ b/net/nimble/controller/src/ble_ll_conn.c @@ -1302,6 +1302,8 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, connsm->slave_latency = hcc->conn_latency; connsm->supervision_tmo = hcc->supervision_timeout; + /* WWW: if not using whitelist, what happens if we resolve the address? + we would have to set the differently huh? CHeck this out... */ /* Set own address type and peer address if needed */ connsm->own_addr_type = hcc->own_addr_type; if (hcc->filter_policy == 0) { @@ -1775,6 +1777,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime) ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); } } + /* WWW: enhanced connection complete! */ ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS); } @@ -2744,14 +2747,13 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap) * @return 0: connection not started; 1 connecton started */ int -ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end) +ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t resolved) { int rc; uint32_t temp; uint32_t crcinit; uint8_t *inita; uint8_t *dptr; - uint8_t addr_type; struct ble_ll_conn_sm *connsm; /* Ignore the connection request if we are already connected*/ @@ -2759,12 +2761,13 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end) SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { if (!memcmp(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN)) { if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { - addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM; + if (connsm->peer_addr_type & 1) { + return 0; + } } else { - addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC; - } - if (connsm->peer_addr_type == addr_type) { - return 0; + if ((connsm->peer_addr_type & 1) == 0) { + return 0; + } } } } @@ -2821,13 +2824,22 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end) goto err_slave_start; } - /* XXX: might want to set this differently based on adv. filter policy! */ + /* WWW: what about master when it makes a connection? It has to do this + properly! */ /* Set the address of device that we are connecting with */ - memcpy(&connsm->peer_addr, rxbuf + BLE_LL_PDU_HDR_LEN, BLE_DEV_ADDR_LEN); + memcpy(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN); if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) { - connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM; + if (resolved) { + connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT; + } else { + connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM; + } } else { - connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC; + if (resolved) { + connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT; + } else { + connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC; + } } /* Calculate number of used channels; make sure it meets min requirement */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_conn_priv.h ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h b/net/nimble/controller/src/ble_ll_conn_priv.h index 4cfd041..24a7a1e 100644 --- a/net/nimble/controller/src/ble_ll_conn_priv.h +++ b/net/nimble/controller/src/ble_ll_conn_priv.h @@ -92,7 +92,8 @@ void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm, struct ble_ll_len_req *req); /* Advertising interface */ -int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end); +int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, + uint8_t resolved); /* Link Layer interface */ void ble_ll_conn_module_init(void); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_ctrl.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c index aee7c83..73a5ac2 100644 --- a/net/nimble/controller/src/ble_ll_ctrl.c +++ b/net/nimble/controller/src/ble_ll_ctrl.c @@ -25,8 +25,8 @@ #include "controller/ble_ll.h" #include "controller/ble_ll_hci.h" #include "controller/ble_ll_ctrl.h" -#include "ble_ll_conn_priv.h" #include "controller/ble_hw.h" +#include "ble_ll_conn_priv.h" /* To use spec sample data for testing */ #undef BLE_LL_ENCRYPT_USE_TEST_DATA http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_hci.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c index 862eebc..3cbec48 100644 --- a/net/nimble/controller/src/ble_ll_hci.c +++ b/net/nimble/controller/src/ble_ll_hci.c @@ -30,6 +30,7 @@ #include "controller/ble_ll.h" #include "controller/ble_ll_hci.h" #include "controller/ble_ll_whitelist.h" +#include "controller/ble_ll_resolv.h" #include "ble_ll_conn_priv.h" /* LE event mask */ @@ -639,6 +640,32 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen) rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf); break; #endif +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + case BLE_HCI_OCF_LE_ADD_RESOLV_LIST : + ble_ll_resolv_list_add(cmdbuf); + break; + case BLE_HCI_OCF_LE_RMV_RESOLV_LIST: + ble_ll_resolv_list_rmv(cmdbuf); + break; + case BLE_HCI_OCF_LE_CLR_RESOLV_LIST: + rc = ble_ll_resolv_list_clr(); + break; + case BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE: + rc = ble_ll_resolv_list_read_size(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR: + rc = ble_ll_resolv_peer_addr_rd(cmdbuf); + break; + case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR: + ble_ll_resolv_local_addr_rd(cmdbuf); + break; + case BLE_HCI_OCF_LE_SET_ADDR_RES_EN: + rc = ble_ll_resolv_enable_cmd(cmdbuf); + break; + case BLE_HCI_OCF_LE_SET_RPA_TMO: + /* XXX: implement */ + break; +#endif case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN: rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen); break; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_rand.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_rand.c b/net/nimble/controller/src/ble_ll_rand.c index f0e69f7..4da599f 100644 --- a/net/nimble/controller/src/ble_ll_rand.c +++ b/net/nimble/controller/src/ble_ll_rand.c @@ -103,6 +103,32 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len) } /** + * Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2 + * + * @param prand + */ +void +ble_ll_rand_prand_get(uint8_t *prand) +{ + uint16_t sum; + + while (1) { + /* Get 24 bits of random data */ + ble_ll_rand_data_get(prand, 3); + + /* Prand cannot be all zeros or 1's. */ + sum = prand[0] + prand[1] + prand[2]; + if ((sum != 0) && (sum != (3 * 0xff))) { + break; + } + } + + /* Upper two bits must be 01 */ + prand[2] &= ~0xc0; + prand[2] |= 0x40; +} + +/** * Start the generation of random numbers * * @return int http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_resolv.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_resolv.c b/net/nimble/controller/src/ble_ll_resolv.c new file mode 100644 index 0000000..62d85e4 --- /dev/null +++ b/net/nimble/controller/src/ble_ll_resolv.c @@ -0,0 +1,378 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include <stdint.h> +#include <assert.h> +#include <string.h> +#include "os/os.h" +#include "nimble/ble.h" +#include "nimble/nimble_opt.h" +#include "controller/ble_ll.h" +#include "controller/ble_ll_resolv.h" +#include "controller/ble_ll_hci.h" +#include "controller/ble_ll_scan.h" +#include "controller/ble_ll_adv.h" +#include "controller/ble_hw.h" +#include "ble_ll_conn_priv.h" + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + +/* Flag denoting whether or not address translation is enabled. */ +uint8_t g_ble_ll_addr_res_enabled; +uint8_t g_ble_ll_resolv_list_size; +uint8_t g_ble_ll_resolv_list_cnt; + +struct ble_ll_resolv_entry g_ble_ll_resolv_list[NIMBLE_OPT_LL_RESOLV_LIST_SIZE]; + +/** + * Called to determine if a change is allowed to the resolving list at this + * time. We are not allowed to modify the resolving list if address translation + * is enabled and we are either scanning, advertising, or attempting to create + * a connection. + * + * @return int 0: not allowed. 1: allowed. + */ +static int +ble_ll_resolv_list_chg_allowed(void) +{ + int rc; + + if (g_ble_ll_addr_res_enabled && (ble_ll_adv_enabled() || + ble_ll_scan_enabled() || + g_ble_ll_conn_create_sm)) { + rc = 0; + } else { + rc = 1; + } + return rc; +} + +/** + * Called to determine if the IRK is all zero. + * + * @param irk + * + * @return int 0: IRK has a non-zero value. 1: IRK is all zero. + */ +int +ble_ll_resolv_irk_nonzero(uint8_t *irk) +{ + int i; + int rc; + + rc = 1; + for (i = 0; i < 16; ++i) { + if (*irk != 0) { + rc = 0; + break; + } + ++irk; + } + + return rc; +} + +/** + * Clear the resolving list + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_resolv_list_clr(void) +{ + /* Check proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Sets total on list to 0. Clears HW resolve list */ + g_ble_ll_resolv_list_cnt = 0; + ble_hw_resolv_list_clear(); + + return BLE_ERR_SUCCESS; +} + +/** + * Read the size of the resolving list. This is the total number of resolving + * list entries allowed by the controller. + * + * @param rspbuf Pointer to response buffer + * + * @return int 0: success. + */ +int +ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen) +{ + rspbuf[0] = g_ble_ll_resolv_list_size; + *rsplen = 1; + return BLE_ERR_SUCCESS; +} + +/** + * Used to determine if the device is on the resolving list. + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * + * @return int 0: device is not on resolving list; otherwise the return value + * is the 'position' of the device in the resolving list (the index of the + * element plus 1). + */ +static int +ble_ll_is_on_resolv_list(uint8_t *addr, uint8_t addr_type) +{ + int i; + struct ble_ll_resolv_entry *rl; + + rl = &g_ble_ll_resolv_list[0]; + for (i = 0; i < g_ble_ll_resolv_list_cnt; ++i) { + if ((rl->rl_addr_type == addr_type) && + (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { + return i + 1; + } + ++rl; + } + + return 0; +} + +/** + * Used to determine if the device is on the resolving list. + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * + * @return Pointer to resolving list entry or NULL if no entry found. + */ +struct ble_ll_resolv_entry * +ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type) +{ + int i; + struct ble_ll_resolv_entry *rl; + + rl = &g_ble_ll_resolv_list[0]; + for (i = 0; i < g_ble_ll_resolv_list_cnt; ++i) { + if ((rl->rl_addr_type == addr_type) && + (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) { + return rl; + } + ++rl; + } + + return NULL; +} + +/** + * Is there a match between the device and a device on the resolving list + * + * @param addr + * @param addr_type Public address (0) or random address (1) + * + * @return int + */ +int +ble_ll_resolv_list_match(uint8_t *addr, uint8_t addr_type) +{ + int rc; + /* WWW: will this be used? */ +#ifdef BLE_USES_HW_RESOLV_LIST + rc = ble_hw_resolv_list_match(); +#else + rc = ble_ll_is_on_resolv_list(addr, addr_type); +#endif + return rc; +} + +/** + * Add a device to the resolving list + * + * @return int + */ +int +ble_ll_resolv_list_add(uint8_t *cmdbuf) +{ + int rc; + uint8_t addr_type; + uint8_t *ident_addr; + struct ble_ll_resolv_entry *rl; + + /* Must be in proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Check if we have any open entries */ + if (g_ble_ll_resolv_list_cnt >= g_ble_ll_resolv_list_size) { + return BLE_ERR_MEM_CAPACITY; + } + + addr_type = cmdbuf[0]; + ident_addr = cmdbuf + 1; + + rc = BLE_ERR_SUCCESS; + if (!ble_ll_is_on_resolv_list(ident_addr, addr_type)) { + rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_list_cnt]; + rl->rl_addr_type = addr_type; + memcpy(&rl->rl_identity_addr[0], ident_addr, BLE_DEV_ADDR_LEN); + swap_buf(rl->rl_peer_irk, cmdbuf + 7, 16); + swap_buf(rl->rl_local_irk, cmdbuf + 23, 16); + ++g_ble_ll_resolv_list_cnt; + + rc = ble_hw_resolv_list_add(rl->rl_peer_irk); + } + + return rc; +} + +/** + * Remove a device from the resolving list + * + * @param cmdbuf + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_ll_resolv_list_rmv(uint8_t *cmdbuf) +{ + int position; + uint8_t addr_type; + uint8_t *ident_addr; + + /* Must be in proper state */ + if (!ble_ll_resolv_list_chg_allowed()) { + return BLE_ERR_CMD_DISALLOWED; + } + + addr_type = cmdbuf[0]; + ident_addr = cmdbuf + 1; + + /* Remove from IRK records */ + position = ble_ll_is_on_resolv_list(ident_addr, addr_type); + if (position && (position < g_ble_ll_resolv_list_cnt)) { + memmove(&g_ble_ll_resolv_list[position - 1], + &g_ble_ll_resolv_list[position], + g_ble_ll_resolv_list_cnt - position); + --g_ble_ll_resolv_list_cnt; + + /* Remove from HW list */ + ble_hw_resolv_list_rmv(position - 1); + } + + return BLE_ERR_SUCCESS; +} + +/** + * Called to enable or disable address resolution in the controller + * + * @param cmdbuf + * + * @return int + */ +int +ble_ll_resolv_enable_cmd(uint8_t *cmdbuf) +{ + int rc; + + if (ble_ll_adv_enabled() || ble_ll_scan_enabled() || + g_ble_ll_conn_create_sm) { + rc = BLE_ERR_CMD_DISALLOWED; + } else { + /* WWW: do we do anything here if we change state? */ + g_ble_ll_addr_res_enabled = cmdbuf[0]; + rc = BLE_ERR_SUCCESS; + } + + return rc; +} + +int +ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf) +{ + /* XXX */ + return 0; +} + +void +ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf) +{ +} + +/** + * Called the generate a resolvable private address + * + * + * @param rl + * @param local + * @param addr Pointer to resolvable private address + */ +void +ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local, + uint8_t *addr) +{ + uint8_t *irk; + uint8_t *prand; + struct ble_encryption_block ecb; + + assert(rl != NULL); + assert(addr != NULL); + + /* Get prand */ + prand = addr + 3; + ble_ll_rand_prand_get(prand); + + /* Calculate hash, hash = ah(local IRK, prand) */ + if (local) { + irk = rl->rl_local_irk; + } else { + irk = rl->rl_peer_irk; + } + + memcpy(ecb.key, irk, BLE_ENC_BLOCK_SIZE); + memset(ecb.plain_text, 0, BLE_ENC_BLOCK_SIZE); + swap_buf(&ecb.plain_text[13], prand, 3); + + /* Calculate hash */ + ble_hw_encrypt_block(&ecb); + swap_buf(addr, ecb.cipher_text, 3); +} + +/** + * Returns whether or not address resolution is enabled. + * + * @return uint8_t + */ +uint8_t +ble_ll_resolv_enabled(void) +{ + return g_ble_ll_addr_res_enabled; +} + +/** + * Called to reset private address resolution module. + */ +void +ble_ll_resolv_list_reset(void) +{ + ble_ll_resolv_list_clr(); + g_ble_ll_addr_res_enabled = 0; + /* XXX: deal with HW restrictions */ + g_ble_ll_resolv_list_size = NIMBLE_OPT_LL_RESOLV_LIST_SIZE; +} + +#endif /* if BLE_LL_CFG_FEAT_LL_PRIVACY == 1 */ + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/controller/src/ble_ll_scan.c ---------------------------------------------------------------------- diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c index 7ebfc46..f675ec7 100644 --- a/net/nimble/controller/src/ble_ll_scan.c +++ b/net/nimble/controller/src/ble_ll_scan.c @@ -392,6 +392,8 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf, evbuf[3] = 1; /* number of reports */ evbuf[4] = evtype; + /* WWW: Yeah... if we are using private resolvable addresses + we need to deal here. The address type is different... */ /* XXX: need to deal with resolvable addresses here! */ if (txadd) { evbuf[5] = BLE_HCI_ADV_OWN_ADDR_RANDOM; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/drivers/nrf51/src/ble_hw.c ---------------------------------------------------------------------- diff --git a/net/nimble/drivers/nrf51/src/ble_hw.c b/net/nimble/drivers/nrf51/src/ble_hw.c index cc9dcbd..498840d 100644 --- a/net/nimble/drivers/nrf51/src/ble_hw.c +++ b/net/nimble/drivers/nrf51/src/ble_hw.c @@ -6,7 +6,7 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, @@ -22,23 +22,45 @@ #include <string.h> #include "os/os.h" #include "nimble/ble.h" +#include "nimble/nimble_opt.h" #include "mcu/nrf51_bitfields.h" #include "controller/ble_hw.h" #include "bsp/cmsis_nvic.h" -/* Total number of white list elements supported by nrf52 */ +/* Total number of white list elements */ #define BLE_HW_WHITE_LIST_SIZE (8) +/* Total number of resolving list elements */ +#define BLE_HW_RESOLV_LIST_SIZE (16) + /* We use this to keep track of which entries are set to valid addresses */ static uint8_t g_ble_hw_whitelist_mask; /* Random number generator isr callback */ ble_rng_isr_cb_t g_ble_rng_isr_cb; +/* If LL privacy is enabled, allocate memory for AAR */ +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + +/* The NRF51 supports up to 16 IRK entries */ +#if (NIMBLE_OPT_LL_RESOLV_LIST_SIZE < 16) +#define NRF_IRK_LIST_ENTRIES (NIMBLE_OPT_LL_RESOLV_LIST_SIZE) +#else +#define NRF_IRK_LIST_ENTRIES (16) +#endif + +/* NOTE: each entry is 16 bytes long. */ +uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; + +/* Current number of IRK entries */ +uint8_t g_nrf_num_irks; + +#endif + /** * Clear the whitelist - * - * @return int + * + * @return int */ void ble_hw_whitelist_clear(void) @@ -48,11 +70,11 @@ ble_hw_whitelist_clear(void) } /** - * Add a device to the hw whitelist - * - * @param addr - * @param addr_type - * + * Add a device to the hw whitelist + * + * @param addr + * @param addr_type + * * @return int 0: success, BLE error code otherwise */ int @@ -80,11 +102,11 @@ ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type) } /** - * Remove a device from the hw whitelist - * - * @param addr - * @param addr_type - * + * Remove a device from the hw whitelist + * + * @param addr + * @param addr_type + * */ void ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type) @@ -126,8 +148,8 @@ ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type) } /** - * Returns the size of the whitelist in HW - * + * Returns the size of the whitelist in HW + * * @return int Number of devices allowed in whitelist */ uint8_t @@ -137,7 +159,7 @@ ble_hw_whitelist_size(void) } /** - * Enable the whitelisted devices + * Enable the whitelisted devices */ void ble_hw_whitelist_enable(void) @@ -147,7 +169,7 @@ ble_hw_whitelist_enable(void) } /** - * Disables the whitelisted devices + * Disables the whitelisted devices */ void ble_hw_whitelist_disable(void) @@ -157,10 +179,10 @@ ble_hw_whitelist_disable(void) } /** - * Boolean function which returns true ('1') if there is a match on the - * whitelist. - * - * @return int + * Boolean function which returns true ('1') if there is a match on the + * whitelist. + * + * @return int */ int ble_hw_whitelist_match(void) @@ -173,9 +195,12 @@ int ble_hw_encrypt_block(struct ble_encryption_block *ecb) { int rc; + uint32_t end; + uint32_t err; /* Stop ECB */ NRF_ECB->TASKS_STOPECB = 1; + /* XXX: does task stop clear these counters? Anyway to do this quicker? */ NRF_ECB->EVENTS_ENDECB = 0; NRF_ECB->EVENTS_ERRORECB = 0; NRF_ECB->ECBDATAPTR = (uint32_t)ecb; @@ -184,14 +209,14 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb) NRF_ECB->TASKS_STARTECB = 1; /* Wait till error or done */ + rc = 0; while (1) { - if (NRF_ECB->EVENTS_ENDECB != 0) { - rc = 0; - break; - } - - if (NRF_ECB->EVENTS_ERRORECB != 0) { - rc = -1; + end = NRF_ECB->EVENTS_ENDECB; + err = NRF_ECB->EVENTS_ERRORECB; + if (end || err) { + if (err) { + rc = -1; + } break; } } @@ -225,11 +250,11 @@ ble_rng_isr(void) /** * Initialize the random number generator - * - * @param cb - * @param bias - * - * @return int + * + * @param cb + * @param bias + * + * @return int */ int ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) @@ -254,8 +279,8 @@ ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) /** * Start the random number generator - * - * @return int + * + * @return int */ int ble_hw_rng_start(void) @@ -278,8 +303,8 @@ ble_hw_rng_start(void) /** * Stop the random generator - * - * @return int + * + * @return int */ int ble_hw_rng_stop(void) @@ -298,8 +323,8 @@ ble_hw_rng_stop(void) /** * Read the random number generator. - * - * @return uint8_t + * + * @return uint8_t */ uint8_t ble_hw_rng_read(void) @@ -315,3 +340,93 @@ ble_hw_rng_read(void) return rnum; } + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY) +/** + * Clear the resolving list + * + * @return int + */ +void +ble_hw_resolv_list_clear(void) +{ + g_nrf_num_irks = 0; +} + +/** + * Add a device to the hw resolving list + * + * @param irk Pointer to IRK to add + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_resolv_list_add(uint8_t *irk) +{ + uint32_t *nrf_entry; + + /* Find first ununsed device address match element */ + if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Copy into irk list */ + nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; + memcpy(nrf_entry, irk, 16); + + /* Add to total */ + ++g_nrf_num_irks; + return BLE_ERR_SUCCESS; +} + +/** + * Remove a device from the hw resolving list + * + * @param index Index of IRK to remove + */ +void +ble_hw_resolv_list_rmv(int index) +{ + uint32_t *irk_entry; + + if (index < g_nrf_num_irks) { + --g_nrf_num_irks; + irk_entry = &g_nrf_irk_list[index]; + if (g_nrf_num_irks > index) { + memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index); + } + } +} + +/** + * Returns the size of the whitelist in HW + * + * @return int Number of devices allowed in whitelist + */ +uint8_t +ble_hw_resolv_list_size(void) +{ + return BLE_HW_RESOLV_LIST_SIZE; +} + +/** + * Called to determine if the address received was resolved. + * + * @return int Negative values indicate unresolved address; positive values + * indicate index in resolving list of resolved address. + */ +int +ble_hw_resolv_list_match(void) +{ + uint32_t index; + + if (NRF_AAR->EVENTS_END) { + if (NRF_AAR->EVENTS_RESOLVED) { + index = NRF_AAR->STATUS; + return (int)index; + } + } + + return -1; +} +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/drivers/nrf51/src/ble_phy.c ---------------------------------------------------------------------- diff --git a/net/nimble/drivers/nrf51/src/ble_phy.c b/net/nimble/drivers/nrf51/src/ble_phy.c index e0f1fb2..e44b04d 100644 --- a/net/nimble/drivers/nrf51/src/ble_phy.c +++ b/net/nimble/drivers/nrf51/src/ble_phy.c @@ -41,6 +41,10 @@ * crystal accuracy */ +/* XXX: private header file? */ +extern uint8_t g_nrf_num_irks; +extern uint32_t g_nrf_irk_list[]; + /* To disable all radio interrupts */ #define NRF_RADIO_IRQ_MASK_ALL (0x34FF) @@ -76,7 +80,9 @@ struct ble_phy_obj uint8_t phy_transition; uint8_t phy_rx_started; uint8_t phy_encrypted; + uint8_t phy_privacy; uint8_t phy_tx_pyld_len; + uint32_t phy_aar_scratch; uint32_t phy_access_address; struct os_mbuf *rxpdu; void *txend_arg; @@ -159,7 +165,7 @@ STATS_NAME_END(ble_phy_stats) */ #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) - +/* XXX: test this. only needs 43 bytes. Should just not use the macro for this*/ /* Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE */ #define NRF_ENC_SCRATCH_WORDS (((NIMBLE_OPT_LL_MAX_PKT_SIZE + 16) + 3) / 4) @@ -254,8 +260,30 @@ ble_phy_rx_xcvr_setup(void) NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; #endif - /* We dont want to trigger TXEN on output compare match */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + if (g_ble_phy_data.phy_privacy) { + NRF_RADIO->PCNF0 = (6 << RADIO_PCNF0_LFLEN_Pos) | + (2 << RADIO_PCNF0_S1LEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; + NRF_AAR->ADDRPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + } else { + if (g_ble_phy_data.phy_encrypted == 0) { + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + /* XXX: do I only need to do this once? Figure out what I can do + once. */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + } + } +#endif + + /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; /* Reset the rx started flag. Used for the wait for response */ g_ble_phy_data.phy_rx_started = 0; @@ -284,8 +312,8 @@ ble_phy_rx_xcvr_setup(void) static void ble_phy_tx_end_isr(void) { - uint8_t txlen; uint8_t transition; + uint8_t txlen; uint32_t wfr_time; /* Better be in TX state! */ @@ -416,8 +444,8 @@ ble_phy_rx_end_isr(void) rxpdu = g_ble_phy_data.rxpdu; g_ble_phy_data.rxpdu = NULL; -#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) - if (g_ble_phy_data.phy_encrypted) { +#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) || (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + if (g_ble_phy_data.phy_encrypted || g_ble_phy_data.phy_privacy) { /* * XXX: This is a horrible ugly hack to deal with the RAM S1 byte. * This should get fixed as we should not be handing up the header @@ -479,6 +507,15 @@ ble_phy_rx_start_isr(void) /* Set rx started flag and enable rx end ISR */ g_ble_phy_data.phy_rx_started = 1; NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + /* Must start aar if we need to */ + if (g_ble_phy_data.phy_privacy) { + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; + NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8; + } +#endif } else { /* Disable PHY */ ble_phy_disable(); @@ -584,11 +621,20 @@ ble_phy_init(void) #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) NRF_CCM->INTENCLR = 0xffffffff; NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; NRF_CCM->EVENTS_ERROR = 0; memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); #endif +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + g_ble_phy_data.phy_aar_scratch = 0; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->INTENCLR = 0xffffffff; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + NRF_AAR->NIRK = 0; +#endif + /* Set isr in vector table and enable interrupt */ NVIC_SetPriority(RADIO_IRQn, 0); NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); @@ -675,6 +721,10 @@ ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, NRF_RADIO->PCNF0 = (5 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos) | (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + + /* Enable the module (AAR cannot be on while CCM on) */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; } void @@ -690,6 +740,7 @@ ble_phy_encrypt_disable(void) NRF_PPI->CHENCLR = (PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk); NRF_CCM->TASKS_STOP = 1; NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; /* Switch back to normal length */ NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | @@ -809,9 +860,16 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans) NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->MODE = CCM_MODE_MODE_Encryption; NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk | PPI_CHEN_CH23_Msk; NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk; } else { + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + /* Reconfigure PCNF0 */ + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; +#endif /* RAM representation has S0 and LENGTH fields (2 bytes) */ dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; dptr[0] = ble_hdr->txinfo.hdr_byte; @@ -819,12 +877,21 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans) dptr += 2; } #else + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + /* Reconfigure PCNF0 */ + NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | + (NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos); + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; +#endif + /* RAM representation has S0 and LENGTH fields (2 bytes) */ dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; dptr[0] = ble_hdr->txinfo.hdr_byte; dptr[1] = payload_len; dptr += 2; #endif + NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_txrx_buf[0]; /* Clear the ready, end and disabled events */ @@ -1015,7 +1082,7 @@ ble_phy_disable(void) NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; NRF_RADIO->SHORTS = 0; NRF_RADIO->TASKS_DISABLE = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk; NVIC_ClearPendingIRQ(RADIO_IRQn); g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; } @@ -1061,13 +1128,6 @@ ble_phy_xcvr_state_get(void) return (uint8_t)state; } -/* - * Returns the maximum supported tx/rx PDU payload size, in bytes, for data - * channel PDUs (this does not apply to advertising channel PDUs). Note - * that the data channel PDU is composed of a 2-byte header, the payload, and - * an optional MIC. The maximum payload is 251 bytes. - */ - /** * Called to return the maximum data pdu payload length supported by the * phy. For this chip, if encryption is enabled, the maximum payload is 27 @@ -1084,3 +1144,18 @@ ble_phy_max_data_pdu_pyld(void) return BLE_LL_DATA_PDU_MAX_PYLD; #endif } + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +void +ble_phy_resolv_list_enable(void) +{ + NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; + g_ble_phy_data.phy_privacy = 1; +} + +void +ble_phy_resolv_list_disable(void) +{ + g_ble_phy_data.phy_privacy = 0; +} +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/drivers/nrf52/src/ble_hw.c ---------------------------------------------------------------------- diff --git a/net/nimble/drivers/nrf52/src/ble_hw.c b/net/nimble/drivers/nrf52/src/ble_hw.c index aacd983..ea32ce4 100644 --- a/net/nimble/drivers/nrf52/src/ble_hw.c +++ b/net/nimble/drivers/nrf52/src/ble_hw.c @@ -22,19 +22,41 @@ #include <string.h> #include "os/os.h" #include "nimble/ble.h" -#include "controller/ble_hw.h" +#include "nimble/nimble_opt.h" #include "mcu/nrf52_bitfields.h" +#include "controller/ble_hw.h" #include "bsp/cmsis_nvic.h" -/* Total number of white list elements supported by nrf52 */ +/* Total number of white list elements */ #define BLE_HW_WHITE_LIST_SIZE (8) +/* Total number of resolving list elements */ +#define BLE_HW_RESOLV_LIST_SIZE (16) + /* We use this to keep track of which entries are set to valid addresses */ static uint8_t g_ble_hw_whitelist_mask; /* Random number generator isr callback */ ble_rng_isr_cb_t g_ble_rng_isr_cb; +/* If LL privacy is enabled, allocate memory for AAR */ +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + +/* The NRF51 supports up to 16 IRK entries */ +#if (NIMBLE_OPT_LL_RESOLV_LIST_SIZE < 16) +#define NRF_IRK_LIST_ENTRIES (NIMBLE_OPT_LL_RESOLV_LIST_SIZE) +#else +#define NRF_IRK_LIST_ENTRIES (16) +#endif + +/* NOTE: each entry is 16 bytes long. */ +uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; + +/* Current number of IRK entries */ +uint8_t g_nrf_num_irks; + +#endif + /** * Clear the whitelist * @@ -318,3 +340,93 @@ ble_hw_rng_read(void) return rnum; } + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY) +/** + * Clear the resolving list + * + * @return int + */ +void +ble_hw_resolv_list_clear(void) +{ + g_nrf_num_irks = 0; +} + +/** + * Add a device to the hw resolving list + * + * @param irk Pointer to IRK to add + * + * @return int 0: success, BLE error code otherwise + */ +int +ble_hw_resolv_list_add(uint8_t *irk) +{ + uint32_t *nrf_entry; + + /* Find first ununsed device address match element */ + if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { + return BLE_ERR_MEM_CAPACITY; + } + + /* Copy into irk list */ + nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; + memcpy(nrf_entry, irk, 16); + + /* Add to total */ + ++g_nrf_num_irks; + return BLE_ERR_SUCCESS; +} + +/** + * Remove a device from the hw resolving list + * + * @param index Index of IRK to remove + */ +void +ble_hw_resolv_list_rmv(int index) +{ + uint32_t *irk_entry; + + if (index < g_nrf_num_irks) { + --g_nrf_num_irks; + irk_entry = &g_nrf_irk_list[index]; + if (g_nrf_num_irks > index) { + memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index); + } + } +} + +/** + * Returns the size of the whitelist in HW + * + * @return int Number of devices allowed in whitelist + */ +uint8_t +ble_hw_resolv_list_size(void) +{ + return BLE_HW_RESOLV_LIST_SIZE; +} + +/** + * Called to determine if the address received was resolved. + * + * @return int Negative values indicate unresolved address; positive values + * indicate index in resolving list of resolved address. + */ +int +ble_hw_resolv_list_match(void) +{ + uint32_t index; + + if (NRF_AAR->EVENTS_END) { + if (NRF_AAR->EVENTS_RESOLVED) { + index = NRF_AAR->STATUS; + return (int)index; + } + } + + return -1; +} +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/drivers/nrf52/src/ble_phy.c ---------------------------------------------------------------------- diff --git a/net/nimble/drivers/nrf52/src/ble_phy.c b/net/nimble/drivers/nrf52/src/ble_phy.c index 13e75fd..08d0d8d 100644 --- a/net/nimble/drivers/nrf52/src/ble_phy.c +++ b/net/nimble/drivers/nrf52/src/ble_phy.c @@ -36,6 +36,16 @@ /* XXX: 4) Make sure RF is higher priority interrupt than schedule */ +/* + * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal + * and 16ms for a 30ppm crystal! We need to limit PDU size based on + * crystal accuracy + */ + +/* XXX: private header file? */ +extern uint8_t g_nrf_num_irks; +extern uint32_t g_nrf_irk_list[]; + /* To disable all radio interrupts */ #define NRF_RADIO_IRQ_MASK_ALL (0x34FF) @@ -65,7 +75,9 @@ struct ble_phy_obj uint8_t phy_transition; uint8_t phy_rx_started; uint8_t phy_encrypted; + uint8_t phy_privacy; uint8_t phy_tx_pyld_len; + uint32_t phy_aar_scratch; uint32_t phy_access_address; struct os_mbuf *rxpdu; void *txend_arg; @@ -78,6 +90,7 @@ struct ble_phy_obj g_ble_phy_data; static uint32_t g_ble_phy_txrx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) +/* Make sure word-aligned for faster copies */ static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; #endif @@ -249,8 +262,23 @@ ble_phy_rx_xcvr_setup(void) NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; #endif - /* We dont want to trigger TXEN on output compare match */ - NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk; +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + if (g_ble_phy_data.phy_privacy) { + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; + NRF_AAR->ADDRPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; + NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + } else { + if (g_ble_phy_data.phy_encrypted == 0) { + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + } + } +#endif + + /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ + NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk; /* Reset the rx started flag. Used for the wait for response */ g_ble_phy_data.phy_rx_started = 0; @@ -412,7 +440,7 @@ ble_phy_rx_end_isr(void) /* * XXX: This is a horrible ugly hack to deal with the RAM S1 byte * that is not sent over the air but is present here. Simply move the - * data pointer to deal with it. Fix this later. Do this in the nrf52 + * data pointer to deal with it. Fix this later. */ dptr[2] = dptr[1]; dptr[1] = dptr[0]; @@ -469,6 +497,15 @@ ble_phy_rx_start_isr(void) /* Set rx started flag and enable rx end ISR */ g_ble_phy_data.phy_rx_started = 1; NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + /* Must start aar if we need to */ + if (g_ble_phy_data.phy_privacy) { + NRF_RADIO->EVENTS_BCMATCH = 0; + NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; + NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8; + } +#endif } else { /* Disable PHY */ ble_phy_disable(); @@ -576,11 +613,20 @@ ble_phy_init(void) #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1) NRF_CCM->INTENCLR = 0xffffffff; NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; NRF_CCM->EVENTS_ERROR = 0; memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); #endif +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + g_ble_phy_data.phy_aar_scratch = 0; + NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR->INTENCLR = 0xffffffff; + NRF_AAR->EVENTS_END = 0; + NRF_AAR->EVENTS_RESOLVED = 0; + NRF_AAR->EVENTS_NOTRESOLVED = 0; + NRF_AAR->NIRK = 0; +#endif + /* Set isr in vector table and enable interrupt */ NVIC_SetPriority(RADIO_IRQn, 0); NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); @@ -662,6 +708,9 @@ ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, memcpy(g_nrf_ccm_data.iv, iv, 8); g_nrf_ccm_data.dir_bit = is_master; g_ble_phy_data.phy_encrypted = 1; + /* Enable the module (AAR cannot be on while CCM on) */ + NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; } void @@ -677,6 +726,8 @@ ble_phy_encrypt_disable(void) NRF_PPI->CHENCLR = (PPI_CHEN_CH24_Msk | PPI_CHEN_CH25_Msk); NRF_CCM->TASKS_STOP = 1; NRF_CCM->EVENTS_ERROR = 0; + NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; + g_ble_phy_data.phy_encrypted = 0; } #endif @@ -752,7 +803,6 @@ ble_phy_rx_set_start_time(uint32_t cputime) return rc; } - int ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans) { @@ -785,12 +835,18 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans) NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->MODE = CCM_MODE_LENGTH_Msk; NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk | PPI_CHEN_CH23_Msk; NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk; } else { +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; +#endif dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; } #else +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; +#endif dptr = (uint8_t *)&g_ble_phy_txrx_buf[0]; #endif @@ -989,7 +1045,7 @@ ble_phy_disable(void) NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; NRF_RADIO->SHORTS = 0; NRF_RADIO->TASKS_DISABLE = 1; - NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk; NVIC_ClearPendingIRQ(RADIO_IRQn); g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; } @@ -1047,3 +1103,18 @@ ble_phy_max_data_pdu_pyld(void) { return BLE_LL_DATA_PDU_MAX_PYLD; } + +#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1) +void +ble_phy_resolv_list_enable(void) +{ + NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; + g_ble_phy_data.phy_privacy = 1; +} + +void +ble_phy_resolv_list_disable(void) +{ + g_ble_phy_data.phy_privacy = 0; +} +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/host/src/host_hci_cmd.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c index 837e6f4..9763974 100644 --- a/net/nimble/host/src/host_hci_cmd.c +++ b/net/nimble/host/src/host_hci_cmd.c @@ -1203,9 +1203,9 @@ host_hci_cmd_set_resolvable_private_address_timeout(uint16_t timeout, int rc; BLE_HS_DBG_ASSERT( - dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN); + dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_RESPRIV_ADDR_TO_LEN); - host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RESOLV_PRIV_ADDR, + host_hci_write_hdr(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_RPA_TMO, BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN, dst); rc = host_hci_cmd_body_set_resolvable_private_address_timeout(timeout, http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/include/nimble/ble.h ---------------------------------------------------------------------- diff --git a/net/nimble/include/nimble/ble.h b/net/nimble/include/nimble/ble.h index 27ad284..f2e7976 100644 --- a/net/nimble/include/nimble/ble.h +++ b/net/nimble/include/nimble/ble.h @@ -71,7 +71,8 @@ struct ble_mbuf_hdr_rxinfo #define BLE_MBUF_HDR_F_MIC_FAILURE (0x20) #define BLE_MBUF_HDR_F_SCAN_RSP_TXD (0x10) #define BLE_MBUF_HDR_F_SCAN_RSP_CHK (0x08) -#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x07) +#define BLE_MBUF_HDR_F_RESOLVED (0x04) +#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x03) /* Transmit info. NOTE: no flags defined */ struct ble_mbuf_hdr_txinfo @@ -103,6 +104,9 @@ struct ble_mbuf_hdr #define BLE_MBUF_HDR_MIC_FAILURE(hdr) \ ((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_MIC_FAILURE) +#define BLE_MBUF_HDR_RESOLVED(hdr) \ + ((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED) + #define BLE_MBUF_HDR_RX_STATE(hdr) \ ((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/include/nimble/hci_common.h ---------------------------------------------------------------------- diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h index 1007477..67fe6e8 100644 --- a/net/nimble/include/nimble/hci_common.h +++ b/net/nimble/include/nimble/hci_common.h @@ -119,7 +119,7 @@ #define BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR (0x002B) #define BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR (0x002C) #define BLE_HCI_OCF_LE_SET_ADDR_RES_EN (0x002D) -#define BLE_HCI_OCF_LE_SET_RESOLV_PRIV_ADDR (0x002E) +#define BLE_HCI_OCF_LE_SET_RPA_TMO (0x002E) #define BLE_HCI_OCF_LE_RD_MAX_DATA_LEN (0x002F) /* Command Specific Definitions */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7327c542/net/nimble/include/nimble/nimble_opt.h ---------------------------------------------------------------------- diff --git a/net/nimble/include/nimble/nimble_opt.h b/net/nimble/include/nimble/nimble_opt.h index 38fb5a7..57038b3 100644 --- a/net/nimble/include/nimble/nimble_opt.h +++ b/net/nimble/include/nimble/nimble_opt.h @@ -264,6 +264,11 @@ #define NIMBLE_OPT_LL_WHITELIST_SIZE (8) #endif +/* Size of the resolving ist */ +#ifndef NIMBLE_OPT_LL_RESOLV_LIST_SIZE +#define NIMBLE_OPT_LL_RESOLV_LIST_SIZE (4) +#endif + /* * Data length management definitions for connections. These define the maximum * size of the PDU's that will be sent and/or received in a connection. @@ -355,7 +360,7 @@ * is not supported by the nimble controller. */ #ifndef BLE_LL_CFG_FEAT_LL_PRIVACY -#define BLE_LL_CFG_FEAT_LL_PRIVACY (0) +#define BLE_LL_CFG_FEAT_LL_PRIVACY (1) #endif /*