From a75def579885182dd1a36d71d7c0b57c4d589119 Mon Sep 17 00:00:00 2001 From: Christopher Collins Date: Wed, 9 Aug 2017 13:04:18 -0700 Subject: [PATCH 1/3] BLE Host - Automatic own-addr-type resolution This commit adds a new function to the NimBLE host API: /** * Determines the best address type to use for automatic address type * resolution. Calculation of the best address type is done as follows: * * if privacy requested: * if we have a random static address: * --> RPA with static random ID * else * --> RPA with public ID * end * else * if we have a random static address: * --> random static address * else * --> public address * end * end * * @param privacy (0/1) Whether to use a private address. * @param out_addr_type On success, the "own addr type" code gets * written here. * * @return 0 if an address type was successfully inferred. * BLE_HS_ENOADDR if the device does not have a * suitable address. * Other BLE host core code on error. */ int ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type) The motivation for this change is to allow BLE packages to be more self-contained. If a package doesn't care what type of address it uses, it can just use whatever is available. X-Original-Commit: f7d304af11c46976d62244bbaaa329853aed3daf --- nimble/host/include/host/ble_hs_test.h | 3 +- nimble/host/src/ble_hs_id.c | 104 +++++++++++++++++-- nimble/host/src/ble_hs_id_priv.h | 1 + nimble/host/test/src/ble_gap_test.c | 2 +- nimble/host/test/src/ble_hs_id_test.c | 126 ++++++++++++++++++++++++ nimble/host/test/src/ble_hs_test.c | 1 + nimble/host/test/src/ble_hs_test_util.c | 6 +- nimble/host/test/src/ble_hs_test_util.h | 2 +- 8 files changed, 233 insertions(+), 12 deletions(-) create mode 100644 nimble/host/test/src/ble_hs_id_test.c diff --git a/nimble/host/include/host/ble_hs_test.h b/nimble/host/include/host/ble_hs_test.h index da4a5b84f..b05a36e26 100644 --- a/nimble/host/include/host/ble_hs_test.h +++ b/nimble/host/include/host/ble_hs_test.h @@ -40,9 +40,10 @@ int ble_gatt_write_test_all(void); int ble_gatts_notify_test_all(void); int ble_gatts_read_test_suite(void); int ble_gatts_reg_test_all(void); -int ble_hs_hci_test_all(void); int ble_hs_adv_test_all(void); int ble_hs_conn_test_all(void); +int ble_hs_hci_test_all(void); +int ble_hs_id_test_all(void); int ble_l2cap_test_all(void); int ble_os_test_all(void); int ble_sm_lgcy_test_suite(void); diff --git a/nimble/host/src/ble_hs_id.c b/nimble/host/src/ble_hs_id.c index 6130c1f3a..8dd0c0275 100644 --- a/nimble/host/src/ble_hs_id.c +++ b/nimble/host/src/ble_hs_id.c @@ -209,8 +209,8 @@ ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr, return rc; } -int -ble_hs_id_use_addr(uint8_t own_addr_type) +static int +ble_hs_id_addr_type_usable(uint8_t own_addr_type) { uint8_t id_addr_type; int nrpa; @@ -235,11 +235,6 @@ ble_hs_id_use_addr(uint8_t own_addr_type) if (nrpa) { return BLE_HS_ENOADDR; } - - rc = ble_hs_pvcy_ensure_started(); - if (rc != 0) { - return rc; - } break; default: @@ -248,3 +243,98 @@ ble_hs_id_use_addr(uint8_t own_addr_type) return 0; } + +int +ble_hs_id_use_addr(uint8_t own_addr_type) +{ + int rc; + + rc = ble_hs_id_addr_type_usable(own_addr_type); + if (rc != 0) { + return rc; + } + + /* If privacy is being used, make sure RPA rotation is in effect. */ + if (own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT || + own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) { + + rc = ble_hs_pvcy_ensure_started(); + if (rc != 0) { + return rc; + } + } + + return 0; +} + +/** + * Determines the best address type to use for automatic address type + * resolution. Calculation of the best address type is done as follows: + * + * if privacy requested: + * if we have a random static address: + * --> RPA with static random ID + * else + * --> RPA with public ID + * end + * else + * if we have a random static address: + * --> random static address + * else + * --> public address + * end + * end + * + * @param privacy (0/1) Whether to use a private address. + * @param out_addr_type On success, the "own addr type" code gets + * written here. + * + * @return 0 if an address type was successfully inferred. + * BLE_HS_ENOADDR if the device does not have a + * suitable address. + * Other BLE host core code on error. + */ +int +ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type) +{ + static const uint8_t pub_addr_types[] = { + BLE_OWN_ADDR_RANDOM, + BLE_OWN_ADDR_PUBLIC, + }; + static const uint8_t priv_addr_types[] = { + BLE_OWN_ADDR_RPA_RANDOM_DEFAULT, + BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT, + }; + const uint8_t *addr_types; + uint8_t addr_type; + int num_addr_types; + int rc; + int i; + + if (privacy) { + addr_types = priv_addr_types; + num_addr_types = sizeof priv_addr_types / sizeof priv_addr_types[0]; + } else { + addr_types = pub_addr_types; + num_addr_types = sizeof pub_addr_types / sizeof pub_addr_types[0]; + } + + for (i = 0; i < num_addr_types; i++) { + addr_type = addr_types[i]; + + rc = ble_hs_id_addr_type_usable(addr_type); + switch (rc) { + case 0: + *out_addr_type = addr_type; + return 0; + + case BLE_HS_ENOADDR: + break; + + default: + return rc; + } + } + + return BLE_HS_ENOADDR; +} diff --git a/nimble/host/src/ble_hs_id_priv.h b/nimble/host/src/ble_hs_id_priv.h index 1db5483fb..14fffa072 100644 --- a/nimble/host/src/ble_hs_id_priv.h +++ b/nimble/host/src/ble_hs_id_priv.h @@ -30,6 +30,7 @@ void ble_hs_id_set_pub(const uint8_t *pub_addr); int ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, int *out_is_nrpa); int ble_hs_id_use_addr(uint8_t addr_type); +int ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type); #ifdef __cplusplus } diff --git a/nimble/host/test/src/ble_gap_test.c b/nimble/host/test/src/ble_gap_test.c index 2ec3501e1..49d2296b6 100644 --- a/nimble/host/test/src/ble_gap_test.c +++ b/nimble/host/test/src/ble_gap_test.c @@ -58,7 +58,7 @@ static void ble_gap_test_util_init(void) { ble_hs_test_util_init(); - ble_hs_test_util_set_static_rnd_addr(); + ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 }); ble_gap_test_util_reset_cb_info(); } diff --git a/nimble/host/test/src/ble_hs_id_test.c b/nimble/host/test/src/ble_hs_id_test.c new file mode 100644 index 000000000..3c15c215b --- /dev/null +++ b/nimble/host/test/src/ble_hs_id_test.c @@ -0,0 +1,126 @@ +/* + * 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 +#include +#include +#include "testutil/testutil.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_adv.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +static int +ble_hs_id_test_util_infer_auto(int privacy, uint8_t *own_addr_type) +{ + int rc; + + ble_hs_lock(); + rc = ble_hs_id_infer_auto(privacy, own_addr_type); + ble_hs_unlock(); + + return rc; +} + +TEST_CASE(ble_hs_id_test_case_auto_none) +{ + uint8_t own_addr_type; + int rc; + + ble_hs_test_util_init(); + + /* Clear public address. */ + ble_hs_id_set_pub((uint8_t[6]){ 0, 0, 0, 0, 0, 0 }); + + rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type); + TEST_ASSERT_FATAL(rc == BLE_HS_ENOADDR); +} + +TEST_CASE(ble_hs_id_test_case_auto_public) +{ + uint8_t own_addr_type; + int rc; + + ble_hs_test_util_init(); + + rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_PUBLIC); +} + +TEST_CASE(ble_hs_id_test_case_auto_random) +{ + uint8_t own_addr_type; + int rc; + + ble_hs_test_util_init(); + + /* Configure a random address. */ + ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 }); + + rc = ble_hs_id_test_util_infer_auto(0, &own_addr_type); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RANDOM); +} + +TEST_CASE(ble_hs_id_test_case_auto_rpa_pub) +{ + uint8_t own_addr_type; + int rc; + + ble_hs_test_util_init(); + + rc = ble_hs_id_test_util_infer_auto(1, &own_addr_type); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT); +} + +TEST_CASE(ble_hs_id_test_case_auto_rpa_rnd) +{ + uint8_t own_addr_type; + int rc; + + ble_hs_test_util_init(); + + /* Configure a random address. */ + ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 1, 2, 3, 4, 5, 0xc0 }); + + rc = ble_hs_id_test_util_infer_auto(1, &own_addr_type); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT); +} + +TEST_SUITE(ble_hs_id_test_suite_auto) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_hs_id_test_case_auto_none(); + ble_hs_id_test_case_auto_public(); + ble_hs_id_test_case_auto_random(); + ble_hs_id_test_case_auto_rpa_pub(); + ble_hs_id_test_case_auto_rpa_rnd(); +} + +int +ble_hs_id_test_all(void) +{ + ble_hs_id_test_suite_auto(); + + return tu_any_failed; +} diff --git a/nimble/host/test/src/ble_hs_test.c b/nimble/host/test/src/ble_hs_test.c index d08d21b2b..853e6e940 100644 --- a/nimble/host/test/src/ble_hs_test.c +++ b/nimble/host/test/src/ble_hs_test.c @@ -48,6 +48,7 @@ main(int argc, char **argv) ble_hs_adv_test_all(); ble_hs_conn_test_all(); ble_hs_hci_test_all(); + ble_hs_id_test_all(); ble_l2cap_test_all(); ble_os_test_all(); ble_sm_test_all(); diff --git a/nimble/host/test/src/ble_hs_test_util.c b/nimble/host/test/src/ble_hs_test_util.c index 5e7ae82bd..95d2b00d4 100644 --- a/nimble/host/test/src/ble_hs_test_util.c +++ b/nimble/host/test/src/ble_hs_test_util.c @@ -2004,9 +2004,8 @@ ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id, } void -ble_hs_test_util_set_static_rnd_addr(void) +ble_hs_test_util_set_static_rnd_addr(const uint8_t *addr) { - uint8_t addr[6] = { 1, 2, 3, 4, 5, 0xc1 }; int rc; ble_hs_test_util_set_ack( @@ -2432,4 +2431,7 @@ ble_hs_test_util_init(void) TEST_ASSERT_FATAL(rc == 0); ble_hs_test_util_prev_hci_tx_clear(); + + /* Clear random address. */ + ble_hs_test_util_set_static_rnd_addr((uint8_t[6]){ 0, 0, 0, 0, 0, 0 }); } diff --git a/nimble/host/test/src/ble_hs_test_util.h b/nimble/host/test/src/ble_hs_test_util.h index 6e11d468d..42b64c740 100644 --- a/nimble/host/test/src/ble_hs_test_util.h +++ b/nimble/host/test/src/ble_hs_test_util.h @@ -261,7 +261,7 @@ int ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle, uint8_t id, uint16_t result); void ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id, uint16_t exp_result); -void ble_hs_test_util_set_static_rnd_addr(void); +void ble_hs_test_util_set_static_rnd_addr(const uint8_t *addr); struct os_mbuf *ble_hs_test_util_om_from_flat(const void *buf, uint16_t len); int ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a, const struct ble_hs_test_util_flat_attr *b); From 3d5bc69c8576b01032eed3611f11ceb74be8f4c3 Mon Sep 17 00:00:00 2001 From: Christopher Collins Date: Wed, 9 Aug 2017 17:28:34 -0700 Subject: [PATCH 2/3] BLE Host - Allow NULL output params in ID fns. X-Original-Commit: 27dc774b176b14b72e580050d98ba6b76da01337 --- nimble/host/src/ble_hs_id.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/nimble/host/src/ble_hs_id.c b/nimble/host/src/ble_hs_id.c index 8dd0c0275..07ccf7297 100644 --- a/nimble/host/src/ble_hs_id.c +++ b/nimble/host/src/ble_hs_id.c @@ -117,10 +117,14 @@ done: * o BLE_ADDR_PUBLIC * o BLE_ADDR_RANDOM * @param out_id_addr On success, this is reseated to point to the - * retrieved 6-byte identity address. + * retrieved 6-byte identity address. Pass + * NULL if you do not require this + * information. + * @param out_is_nrpa On success, the pointed-to value indicates * whether the retrieved address is a - * non-resolvable private address. + * non-resolvable private address. Pass NULL + * if you do not require this information. * * @return 0 on success; * BLE_HS_EINVAL if an invalid address type was @@ -178,10 +182,12 @@ ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, * o BLE_ADDR_RANDOM * @param out_id_addr On success, the requested identity address is * copied into this buffer. The buffer must - * be at least six bytes in size. + * be at least six bytes in size. Pass NULL + * if you do not require this information. * @param out_is_nrpa On success, the pointed-to value indicates * whether the retrieved address is a - * non-resolvable private address. + * non-resolvable private address. Pass NULL + * if you do not require this information. * * @return 0 on success; * BLE_HS_EINVAL if an invalid address type was @@ -200,7 +206,7 @@ ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr, ble_hs_lock(); rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa); - if (rc == 0) { + if (rc == 0 && out_id_addr != NULL) { memcpy(out_id_addr, addr, 6); } From ab75b3edcdfa42a840a8113db871c3786225690c Mon Sep 17 00:00:00 2001 From: Christopher Collins Date: Wed, 9 Aug 2017 17:29:01 -0700 Subject: [PATCH 3/3] Add function to load at least one BLE addr from hw This is just a helper function, so it is not going in the nimble stack itself. Instead, I have created a supplementary package: net/nimble/host/util. X-Original-Commit: b185ac0bd90c1f3ad3bc481fe1c4ec63a7e8238c --- nimble/host/util/include/host/util/util.h | 33 +++++++ nimble/host/util/pkg.yml | 29 ++++++ nimble/host/util/src/addr.c | 109 ++++++++++++++++++++++ nimble/host/util/syscfg.yml | 21 +++++ 4 files changed, 192 insertions(+) create mode 100644 nimble/host/util/include/host/util/util.h create mode 100644 nimble/host/util/pkg.yml create mode 100644 nimble/host/util/src/addr.c create mode 100644 nimble/host/util/syscfg.yml diff --git a/nimble/host/util/include/host/util/util.h b/nimble/host/util/include/host/util/util.h new file mode 100644 index 000000000..7588192b3 --- /dev/null +++ b/nimble/host/util/include/host/util/util.h @@ -0,0 +1,33 @@ +/* + * 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_HOST_UTIL_ +#define H_HOST_UTIL_ + +#ifdef __cplusplus +extern "C" { +#endif + +int ble_hs_util_ensure_addr(int prefer_random); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/nimble/host/util/pkg.yml b/nimble/host/util/pkg.yml new file mode 100644 index 000000000..3c4b373ff --- /dev/null +++ b/nimble/host/util/pkg.yml @@ -0,0 +1,29 @@ +# +# 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. +# + +pkg.name: net/nimble/host/util +pkg.description: Supplementary utilities for the NimBLE host +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.deps: + - net/nimble/host diff --git a/nimble/host/util/src/addr.c b/nimble/host/util/src/addr.c new file mode 100644 index 000000000..b797fd687 --- /dev/null +++ b/nimble/host/util/src/addr.c @@ -0,0 +1,109 @@ +/* + * 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 "hal/hal_bsp.h" +#include "host/ble_hs.h" +#include "host/util/util.h" + +#if MYNEWT_VAL(BLE_DEVICE) +#include "controller/ble_hw.h" +#endif + +static int +ble_hs_util_load_rand_addr(ble_addr_t *addr) +{ + /* XXX: It is unfortunate that the function to retrieve the random address + * is in the controller package. A host-only device ought to be able to + * automically restore a random address. + */ +#if MYNEWT_VAL(BLE_DEVICE) + int rc; + + rc = ble_hw_get_static_addr(addr); + if (rc == 0) { + return 0; + } +#endif + + return BLE_HS_ENOADDR; +} + +static int +ble_hs_util_ensure_rand_addr(void) +{ + ble_addr_t addr; + int rc; + + /* If we already have a random address, then we are done. */ + rc = ble_hs_id_copy_addr(BLE_ADDR_RANDOM, NULL, NULL); + if (rc == 0) { + return 0; + } + + /* Otherwise, try to load a random address. */ + rc = ble_hs_util_load_rand_addr(&addr); + if (rc != 0) { + return rc; + } + + /* Configure nimble to use the random address. */ + rc = ble_hs_id_set_rnd(addr.val); + if (rc != 0) { + return rc; + } + + return 0; +} + +/** + * Tries to configure the device with at least one Bluetooth address. + * Addresses are restored in a hardware-specific fasion. + * + * @param prefer_random Whether to attempt to restore a random address + * before checking if a public address has + * already been configured. + * + * @return 0 on success; + * BLE_HS_ENOADDR if the device does not have any + * available addresses. + * Other BLE host core code on error. + */ +int +ble_hs_util_ensure_addr(int prefer_random) +{ + int rc; + + if (prefer_random) { + /* Try to load a random address. */ + rc = ble_hs_util_ensure_rand_addr(); + if (rc == BLE_HS_ENOADDR) { + /* No random address; try to load a public address. */ + rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, NULL, NULL); + } + } else { + /* Try to load a public address. */ + rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, NULL, NULL); + if (rc == BLE_HS_ENOADDR) { + /* No random address; try to load a random address. */ + rc = ble_hs_util_ensure_rand_addr(); + } + } + + return rc; +} diff --git a/nimble/host/util/syscfg.yml b/nimble/host/util/syscfg.yml new file mode 100644 index 000000000..8e700bda1 --- /dev/null +++ b/nimble/host/util/syscfg.yml @@ -0,0 +1,21 @@ +# 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. +# + +# Package: net/nimble/host/util + +syscfg.defs: