| /* |
| * 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 <string.h> |
| #include "host/ble_hs_id.h" |
| #include "ble_hs_priv.h" |
| |
| static uint8_t ble_hs_id_pub[6]; |
| static uint8_t ble_hs_id_rnd[6]; |
| |
| void |
| ble_hs_id_set_pub(const uint8_t *pub_addr) |
| { |
| ble_hs_lock(); |
| memcpy(ble_hs_id_pub, pub_addr, 6); |
| ble_hs_unlock(); |
| } |
| |
| int |
| ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr) |
| { |
| int rc; |
| |
| out_addr->type = BLE_ADDR_RANDOM; |
| |
| rc = ble_hs_hci_util_rand(out_addr->val, 6); |
| if (rc != 0) { |
| return rc; |
| } |
| |
| if (nrpa) { |
| out_addr->val[5] &= ~0xc0; |
| } else { |
| out_addr->val[5] |= 0xc0; |
| } |
| |
| return 0; |
| } |
| |
| int |
| ble_hs_id_set_rnd(const uint8_t *rnd_addr) |
| { |
| uint8_t addr_type_byte; |
| int rc; |
| |
| ble_hs_lock(); |
| |
| addr_type_byte = rnd_addr[5] & 0xc0; |
| if (addr_type_byte != 0x00 && addr_type_byte != 0xc0) { |
| rc = BLE_HS_EINVAL; |
| goto done; |
| } |
| |
| rc = ble_hs_hci_util_set_random_addr(rnd_addr); |
| if (rc != 0) { |
| goto done; |
| } |
| |
| memcpy(ble_hs_id_rnd, rnd_addr, 6); |
| |
| rc = 0; |
| |
| done: |
| ble_hs_unlock(); |
| return rc; |
| } |
| |
| /** |
| * Retrieves one of the device's identity addresses. The device can have two |
| * identity addresses: one public and one random. The id_addr_type argument |
| * specifies which of these two addresses to retrieve. |
| * |
| * @param id_addr_type The type of identity address to retrieve. |
| * Valid values are: |
| * 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. 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. Pass NULL |
| * if you do not require this information. |
| * |
| * @return 0 on success; |
| * BLE_HS_EINVAL if an invalid address type was |
| * specified; |
| * BLE_HS_ENOADDR if the device does not have an |
| * identity address of the requested type; |
| * Other BLE host core code on error. |
| */ |
| int |
| ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, |
| int *out_is_nrpa) |
| { |
| const uint8_t *id_addr; |
| int nrpa; |
| |
| BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task()); |
| |
| switch (id_addr_type) { |
| case BLE_ADDR_PUBLIC: |
| id_addr = ble_hs_id_pub; |
| nrpa = 0; |
| break; |
| |
| case BLE_ADDR_RANDOM: |
| id_addr = ble_hs_id_rnd; |
| nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0; |
| break; |
| |
| default: |
| return BLE_HS_EINVAL; |
| } |
| |
| if (memcmp(id_addr, ble_hs_misc_null_addr, 6) == 0) { |
| return BLE_HS_ENOADDR; |
| } |
| |
| if (out_id_addr != NULL) { |
| *out_id_addr = id_addr; |
| } |
| if (out_is_nrpa != NULL) { |
| *out_is_nrpa = nrpa; |
| } |
| |
| return 0; |
| } |
| |
| int |
| ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr, |
| int *out_is_nrpa) |
| { |
| const uint8_t *addr; |
| int rc; |
| |
| ble_hs_lock(); |
| |
| rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa); |
| if (rc == 0 && out_id_addr != NULL) { |
| memcpy(out_id_addr, addr, 6); |
| } |
| |
| ble_hs_unlock(); |
| |
| return rc; |
| } |
| |
| static int |
| ble_hs_id_addr_type_usable(uint8_t own_addr_type) |
| { |
| uint8_t id_addr_type; |
| int nrpa; |
| int rc; |
| |
| switch (own_addr_type) { |
| case BLE_OWN_ADDR_PUBLIC: |
| case BLE_OWN_ADDR_RANDOM: |
| rc = ble_hs_id_addr(own_addr_type, NULL, NULL); |
| if (rc != 0) { |
| return rc; |
| } |
| break; |
| |
| case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT: |
| case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT: |
| id_addr_type = ble_hs_misc_addr_type_to_id(own_addr_type); |
| rc = ble_hs_id_addr(id_addr_type, NULL, &nrpa); |
| if (rc != 0) { |
| return rc; |
| } |
| if (nrpa) { |
| return BLE_HS_ENOADDR; |
| } |
| break; |
| |
| default: |
| return BLE_HS_EINVAL; |
| } |
| |
| 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; |
| } |
| |
| 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; |
| |
| ble_hs_lock(); |
| |
| 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; |
| goto done; |
| |
| case BLE_HS_ENOADDR: |
| break; |
| |
| default: |
| goto done; |
| } |
| } |
| |
| rc = BLE_HS_ENOADDR; |
| |
| done: |
| ble_hs_unlock(); |
| return rc; |
| } |
| |
| /** |
| * Clears both the public and random addresses. This function is necessary |
| * when the controller loses its random address (e.g., on a stack reset). |
| */ |
| void |
| ble_hs_id_reset(void) |
| { |
| memset(ble_hs_id_pub, 0, sizeof ble_hs_id_pub); |
| memset(ble_hs_id_rnd, 0, sizeof ble_hs_id_pub); |
| } |