| /* |
| * Copyright (c) 2021 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/net/buf.h> |
| #include <zephyr/sys/byteorder.h> |
| #include <string.h> |
| |
| #include <zephyr/bluetooth/mesh.h> |
| #include "crypto.h" |
| #include "access.h" |
| |
| int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf, |
| struct bt_mesh_dfu_metadata *metadata) |
| { |
| if (buf->len < 12) { |
| return -EMSGSIZE; |
| } |
| |
| metadata->fw_ver.major = net_buf_simple_pull_u8(buf); |
| metadata->fw_ver.minor = net_buf_simple_pull_u8(buf); |
| metadata->fw_ver.revision = net_buf_simple_pull_le16(buf); |
| metadata->fw_ver.build_num = net_buf_simple_pull_le32(buf); |
| metadata->fw_size = net_buf_simple_pull_le24(buf); |
| metadata->fw_core_type = net_buf_simple_pull_u8(buf); |
| |
| if (metadata->fw_core_type & BT_MESH_DFU_FW_CORE_TYPE_APP) { |
| if (buf->len < 6) { |
| return -EMSGSIZE; |
| } |
| |
| metadata->comp_hash = net_buf_simple_pull_le32(buf); |
| metadata->elems = net_buf_simple_pull_le16(buf); |
| } |
| |
| metadata->user_data = buf->len > 0 ? buf->data : NULL; |
| metadata->user_data_len = buf->len; |
| |
| return 0; |
| } |
| |
| |
| int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata, |
| struct net_buf_simple *buf) |
| { |
| size_t md_len_min = 12 + metadata->user_data_len; |
| |
| if (metadata->fw_core_type & BT_MESH_DFU_FW_CORE_TYPE_APP) { |
| md_len_min += 6; |
| } |
| |
| if (net_buf_simple_tailroom(buf) < md_len_min) { |
| return -EMSGSIZE; |
| } |
| |
| net_buf_simple_add_u8(buf, metadata->fw_ver.major); |
| net_buf_simple_add_u8(buf, metadata->fw_ver.minor); |
| net_buf_simple_add_le16(buf, metadata->fw_ver.revision); |
| net_buf_simple_add_le32(buf, metadata->fw_ver.build_num); |
| net_buf_simple_add_le24(buf, metadata->fw_size); |
| net_buf_simple_add_u8(buf, metadata->fw_core_type); |
| net_buf_simple_add_le32(buf, metadata->comp_hash); |
| net_buf_simple_add_le16(buf, metadata->elems); |
| |
| if (metadata->user_data_len > 0) { |
| net_buf_simple_add_mem(buf, metadata->user_data, metadata->user_data_len); |
| } |
| |
| return 0; |
| } |
| |
| int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash) |
| { |
| uint8_t mac[16]; |
| int err; |
| struct bt_mesh_sg sg = {.data = buf->data, .len = buf->len}; |
| |
| err = bt_mesh_aes_cmac_raw_key(key, &sg, 1, mac); |
| if (err) { |
| return err; |
| } |
| |
| *hash = sys_get_le32(mac); |
| |
| return 0; |
| } |
| |
| int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash) |
| { |
| NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_TX_SDU_MAX); |
| int err; |
| |
| err = bt_mesh_comp_data_get_page_0(&buf, 0); |
| if (err) { |
| return err; |
| } |
| |
| err = bt_mesh_dfu_metadata_comp_hash_get(&buf, key, hash); |
| return err; |
| } |