1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/net_buf.h>
8 #include <zephyr/sys/byteorder.h>
9 #include <string.h>
10 
11 #include <zephyr/bluetooth/mesh.h>
12 #include "crypto.h"
13 #include "access.h"
14 
bt_mesh_dfu_metadata_decode(struct net_buf_simple * buf,struct bt_mesh_dfu_metadata * metadata)15 int bt_mesh_dfu_metadata_decode(struct net_buf_simple *buf,
16 				struct bt_mesh_dfu_metadata *metadata)
17 {
18 	if (buf->len < 12) {
19 		return -EMSGSIZE;
20 	}
21 
22 	metadata->fw_ver.major = net_buf_simple_pull_u8(buf);
23 	metadata->fw_ver.minor = net_buf_simple_pull_u8(buf);
24 	metadata->fw_ver.revision = net_buf_simple_pull_le16(buf);
25 	metadata->fw_ver.build_num = net_buf_simple_pull_le32(buf);
26 	metadata->fw_size = net_buf_simple_pull_le24(buf);
27 	metadata->fw_core_type = net_buf_simple_pull_u8(buf);
28 
29 	if (metadata->fw_core_type & BT_MESH_DFU_FW_CORE_TYPE_APP) {
30 		if (buf->len < 6) {
31 			return -EMSGSIZE;
32 		}
33 
34 		metadata->comp_hash = net_buf_simple_pull_le32(buf);
35 		metadata->elems = net_buf_simple_pull_le16(buf);
36 	}
37 
38 	metadata->user_data = buf->len > 0 ? buf->data : NULL;
39 	metadata->user_data_len = buf->len;
40 
41 	return 0;
42 }
43 
44 
bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata * metadata,struct net_buf_simple * buf)45 int bt_mesh_dfu_metadata_encode(const struct bt_mesh_dfu_metadata *metadata,
46 				struct net_buf_simple *buf)
47 {
48 	size_t md_len_min = 12 + metadata->user_data_len;
49 
50 	if (metadata->fw_core_type & BT_MESH_DFU_FW_CORE_TYPE_APP) {
51 		md_len_min += 6;
52 	}
53 
54 	if (net_buf_simple_tailroom(buf) < md_len_min) {
55 		return -EMSGSIZE;
56 	}
57 
58 	net_buf_simple_add_u8(buf, metadata->fw_ver.major);
59 	net_buf_simple_add_u8(buf, metadata->fw_ver.minor);
60 	net_buf_simple_add_le16(buf, metadata->fw_ver.revision);
61 	net_buf_simple_add_le32(buf, metadata->fw_ver.build_num);
62 	net_buf_simple_add_le24(buf, metadata->fw_size);
63 	net_buf_simple_add_u8(buf, metadata->fw_core_type);
64 	net_buf_simple_add_le32(buf, metadata->comp_hash);
65 	net_buf_simple_add_le16(buf, metadata->elems);
66 
67 	if (metadata->user_data_len > 0) {
68 		net_buf_simple_add_mem(buf, metadata->user_data, metadata->user_data_len);
69 	}
70 
71 	return 0;
72 }
73 
bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple * buf,uint8_t * key,uint32_t * hash)74 int bt_mesh_dfu_metadata_comp_hash_get(struct net_buf_simple *buf, uint8_t *key, uint32_t *hash)
75 {
76 	uint8_t mac[16];
77 	int err;
78 	struct bt_mesh_sg sg = {.data = buf->data, .len = buf->len};
79 
80 	err = bt_mesh_aes_cmac_raw_key(key, &sg, 1, mac);
81 	if (err) {
82 		return err;
83 	}
84 
85 	*hash = sys_get_le32(mac);
86 
87 	return 0;
88 }
89 
bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t * key,uint32_t * hash)90 int bt_mesh_dfu_metadata_comp_hash_local_get(uint8_t *key, uint32_t *hash)
91 {
92 	NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_TX_SDU_MAX);
93 	int err;
94 
95 	err = bt_mesh_comp_data_get_page_0(&buf, 0);
96 	if (err) {
97 		return err;
98 	}
99 
100 	err = bt_mesh_dfu_metadata_comp_hash_get(&buf, key, hash);
101 	return err;
102 }
103