| /* |
| * Copyright (c) 2020 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_SUBNET_H_ |
| #define ZEPHYR_SUBSYS_BLUETOOTH_MESH_SUBNET_H_ |
| |
| #include <stdint.h> |
| #include <sys/types.h> |
| #include <zephyr/net/buf.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/sys/iterable_sections.h> |
| |
| #define BT_MESH_NET_FLAG_KR BIT(0) |
| #define BT_MESH_NET_FLAG_IVU BIT(1) |
| |
| #define BT_MESH_KR_NORMAL 0x00 |
| #define BT_MESH_KR_PHASE_1 0x01 |
| #define BT_MESH_KR_PHASE_2 0x02 |
| #define BT_MESH_KR_PHASE_3 0x03 |
| |
| /** Which of the two subnet.keys should be used for sending. */ |
| #define SUBNET_KEY_TX_IDX(sub) ((sub)->kr_phase == BT_MESH_KR_PHASE_2) |
| |
| struct bt_mesh_net_rx; |
| enum bt_mesh_key_evt; |
| |
| /** Network message encryption credentials */ |
| struct bt_mesh_net_cred { |
| uint8_t nid; /* NID */ |
| uint8_t enc[16]; /* EncKey */ |
| uint8_t privacy[16]; /* PrivacyKey */ |
| }; |
| |
| struct bt_mesh_beacon { |
| uint32_t sent; /* Timestamp of last sent beacon */ |
| uint32_t recv; /* Timestamp of last received beacon */ |
| uint8_t last; /* Number of beacons during last |
| * observation window |
| */ |
| uint8_t cur; /* Number of beacons observed during |
| * currently ongoing window. |
| */ |
| uint8_t cache[8]; /* Cached last beacon auth value */ |
| uint8_t auth[8]; /* Beacon Authentication Value */ |
| }; |
| |
| /** Subnet instance. */ |
| struct bt_mesh_subnet { |
| uint16_t net_idx; /* NetKeyIndex */ |
| |
| uint8_t kr_phase; /* Key Refresh Phase */ |
| |
| uint8_t node_id; /* Node Identity State */ |
| uint32_t node_id_start; /* Node Identity started timestamp */ |
| |
| struct bt_mesh_beacon secure_beacon; |
| |
| #if defined(CONFIG_BT_MESH_PRIV_BEACONS) |
| struct bt_mesh_beacon priv_beacon; |
| struct { |
| uint16_t idx; /* Private beacon random index */ |
| bool node_id; /* Private Node Identity enabled */ |
| uint8_t data[5]; /* Private Beacon data */ |
| } priv_beacon_ctx; |
| #endif |
| |
| struct bt_mesh_subnet_keys { |
| bool valid; |
| uint8_t net[16]; /* NetKey */ |
| struct bt_mesh_net_cred msg; |
| uint8_t net_id[8]; /* Network ID */ |
| #if defined(CONFIG_BT_MESH_GATT_PROXY) |
| uint8_t identity[16]; /* IdentityKey */ |
| #endif |
| uint8_t beacon[16]; /* BeaconKey */ |
| #if defined(CONFIG_BT_MESH_V1d1) |
| uint8_t priv_beacon[16]; /* PrivateBeaconKey */ |
| #endif |
| } keys[2]; |
| #if defined(CONFIG_BT_MESH_PROXY_SOLICITATION) |
| bool sol_tx; |
| #endif |
| #if defined(CONFIG_BT_MESH_OD_PRIV_PROXY_SRV) |
| uint32_t priv_net_id_sent; /* Timestamp for Private Network ID advertising |
| * started via Proxy Solicitation |
| */ |
| bool solicited; /* Subnet received valid Solicitation PDU */ |
| #endif |
| }; |
| |
| /** Subnet callback structure. Instantiate with @ref BT_MESH_SUBNET_CB */ |
| struct bt_mesh_subnet_cb { |
| void (*evt_handler)(struct bt_mesh_subnet *subnet, |
| enum bt_mesh_key_evt evt); |
| }; |
| |
| /** |
| * @brief Register a subnet event callback. |
| * |
| * @param _name Handler name. |
| */ |
| #define BT_MESH_SUBNET_CB_DEFINE(_name) \ |
| static const STRUCT_SECTION_ITERABLE( \ |
| bt_mesh_subnet_cb, _CONCAT(bt_mesh_subnet_cb_, _name)) |
| |
| /** @brief Reset all Network keys. */ |
| void bt_mesh_net_keys_reset(void); |
| |
| /** @brief Call cb on every valid Subnet until it returns a non-zero value. |
| * |
| * @param cb Callback to call, or NULL to return first valid subnet. If the callback returns true, |
| * iteration stops, and the passed subnet is returned. |
| * @param cb_data Callback data to pass to callback. |
| * |
| * @return Subnet that returned non-zero value. |
| */ |
| struct bt_mesh_subnet *bt_mesh_subnet_find(bool (*cb)(struct bt_mesh_subnet *sub, void *cb_data), |
| void *cb_data); |
| |
| /** @brief Iterate through all valid Subnets. |
| * |
| * @param cb Callback to call on every Subnet. |
| * |
| * @returns The number of valid subnets. |
| */ |
| size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub)); |
| |
| /** @brief Get the next valid Subnet. |
| * |
| * If there's only one valid Subnet, this will be returned on every call. |
| * |
| * @param sub Previous Subnet, or NULL to get the first valid. |
| * |
| * @returns Gets the next valid Subnet after @c sub, or NULL if there are no |
| * valid Subnets. |
| */ |
| struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub); |
| |
| /** @brief Get a pointer to the Subnet with the given index. |
| * |
| * @param net_idx Network index to look for. |
| * |
| * @returns Subnet with index @c net_idx, or NULL if no such Subnet is known. |
| */ |
| struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx); |
| |
| /** @brief Initialize a new Subnet. |
| * |
| * @param net_idx Network index of the Subnet. |
| * @param kr_phase Key refresh phase the Subnet should be in. |
| * @param key The current network key for the Subnet. |
| * @param new_key New network key, if available. |
| * |
| * @returns 0 on success, or (negative) error code on failure. |
| */ |
| int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase, |
| const uint8_t key[16], const uint8_t new_key[16]); |
| |
| /** @brief Create Friendship credentials. |
| * |
| * @param cred Credential object to create. |
| * @param lpn_addr Address of the LPN node in the friendship. |
| * @param frnd_addr Address of the Friend node in the friendship. |
| * @param lpn_counter The LPN's counter parameter. |
| * @param frnd_counter The Friend node's counter parameter. |
| * @param key Network key to create the Friendship credentials for. |
| * |
| * @returns 0 on success, or (negative) error code on failure. |
| */ |
| int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred, |
| uint16_t lpn_addr, uint16_t frnd_addr, |
| uint16_t lpn_counter, uint16_t frnd_counter, |
| const uint8_t key[16]); |
| |
| /** @brief Iterate through all valid network credentials to decrypt a message. |
| * |
| * @param rx Network RX parameters, passed to the callback. |
| * @param in Input message buffer, passed to the callback. |
| * @param out Output message buffer, passed to the callback. |
| * @param cb Callback to call for each known network credential. Iteration |
| * stops when this callback returns @c true. |
| * |
| * @returns Whether any of the credentials got a @c true return from the |
| * callback. |
| */ |
| bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct net_buf_simple *in, |
| struct net_buf_simple *out, |
| bool (*cb)(struct bt_mesh_net_rx *rx, |
| struct net_buf_simple *in, |
| struct net_buf_simple *out, |
| const struct bt_mesh_net_cred *cred)); |
| |
| /** @brief Get the network flags of the given Subnet. |
| * |
| * @param sub Subnet to get the network flags of. |
| * |
| * @returns A bitmap of @ref BT_MESH_NET_FLAG_KR and @ref BT_MESH_NET_FLAG_IVU. |
| */ |
| uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub); |
| |
| /** @brief Process a Key Refresh event from a beacon. |
| * |
| * @param sub Subnet the Key Refresh was received on. |
| * @param kr_flag Key Refresh flag. |
| * @param new_key Whether the Key Refresh event was received on the new key |
| * set. |
| * |
| * @returns Whether the Key Refresh event caused a change. |
| */ |
| void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key); |
| |
| /** @brief Check whether the Subnet has the refreshed keys. |
| * |
| * @param sub Subnet. |
| * |
| * @returns Whether the Subnet's second key is valid. |
| */ |
| static inline bool |
| bt_mesh_subnet_has_new_key(const struct bt_mesh_subnet *sub) |
| { |
| return sub->kr_phase != BT_MESH_KR_NORMAL; |
| } |
| |
| /** @brief Store the Subnet information in persistent storage. |
| * |
| * @param net_idx Network index to store. |
| */ |
| void bt_mesh_subnet_store(uint16_t net_idx); |
| |
| /** @brief Store the pending Subnets in persistent storage. */ |
| void bt_mesh_subnet_pending_store(void); |
| |
| #endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_SUBNET_H_ */ |