LV04-天猫蓝牙Mesh项目-02-进阶开发-07-蓝牙Mesh密钥生成详解

本文主要是天猫蓝牙Mesh项目——进阶开发 蓝牙Mesh密钥生成详解 的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu22.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
点击查看本文参考资料
分类 网址 说明
官方网站 阿里云 阿里云官网主页
阿里生活物联平台 生活物联网平台(飞燕平台)主页
AliGenie 天猫精灵开放平台AliGenie主页
阿里物联网平台 阿里物联网平台主页
Bluetooth 技术网站 蓝牙协议规范什么的可以来这里找
Telink Telink | Chips for a Smarter IoT (telink-semi.com)
Telink中文官网
开发手册 AliOS Things开发指南 AliOS Things开发指南,这里是最新版本,可以直接从官网找到
AliOS Things开发指南 AliOS Things应用开发指南,这里应该是3.3版本的完整开发文档
AliOS Things开发指南(3.0) AliOS Things应用开发指南,这里应该是3.0版本的完整开发文档
生活物联网平台开发文档 生活物联网平台(飞燕平台)开发文档
《设备端开发指南》
Wi-Fi IoT品类定义与功能开发 天猫精灵IoT开放平台——Wi-Fi IoT品类定义与功能开发
硬件平台 mk3080 WiFi开发板 WiFi开发板使用指南-阿里云开发者社区
esp8266开发板 一个教程:ESP8266-NodeMCU开发板详解-太极创客 (taichi-maker.com)
TLSR8258 Datasheet Datasheet for Telink BLE + IEEE802.15.4 MultiStandard Wireless SoC TLSR8258
参考资料 AliOS Things 3.0 应用开发指南 这个只是一篇参考文章,里面是一些环境搭建相关的,可以参考
IP知识百科 - 华为 (huawei.com) IP的一些相关知识点
点击查看相关文件下载
分类 网址 说明
蓝牙规范相关文档 Core Specification 5.2 核心规格 5.2,该规范定义了创建可互操作的Bluetooth 设备所需的技术。
《Core_v5.2.pdf》
Mesh Model(v1.1) 本Bluetooth 规范定义了模型(以及它们所需的状态和消息),这些模型用于在mesh 网络中的节点上执行基本功能,超出了Bluetooth Mesh 配置文件 规范中定义的基础模型。
本规范包括定义跨设备类型标准功能的通用模型,以及支持关键mesh 场景的模型,如照明控制、传感器、时间和场景。
《MshMDL_v1.1.pdf》
Mesh Profile(v1.0.1) 该Bluetooth 规范定义了基本要求,以实现可互操作的mesh 网络解决方案,用于Bluetooth 低能量无线技术。
《MshPRFv1.0.1.pdf》
Mesh Device Properties 本规范包含Bluetooth Mesh 配置文件 和Bluetooth Mesh 模型规范所要求的设备属性的定义。
但是跟之前的有些区别,我主要看的之前的版本:《MMeshDeviceProperties_v1.2.pdf》
GATT Specification Supplement GATT Specification Supplement | Bluetooth® Technology Website。
好像可以在线看:《GATT Specification Supplement》
Assigned Numbers GATT的一些类型定义可以在这里找。
AliOS Things alios-things/AliOS-Things Gitee上的AliOSThings SDK源码仓库
alibaba/AliOS-Things GitHub上的AliOSThings SDK源码仓库
天猫精灵蓝牙Mesh协议栈 alibaba-archive/genie-bt-mesh-stack GitHub上的天猫精灵蓝牙Mesh协议栈源码仓库。
之前是在alibaba/genie-bt-mesh-stack这个仓库。
写笔记的时候最新提交为faf523618a6a2560090fc423222b9db80984bb7a
蓝牙Mesh设备开发指南 阿里云生活服务平台开发手册——蓝牙设备开发一节中的内容

这一LV的笔记起始跟前面有所重叠,互相补充吧算是。

一、各种密钥生成原理

1. 配网过程中的密钥

1.1 DHKey共享密钥

配网生成共享密钥

HCI中会有控制器生成随机数的命令,我们下发了对应的命令后,就会生成一个随机数。然后就可以用这个随机数作为一个“种子”去生成其他种类的密钥。在协议栈中,基点G是一个常量,双方都有,是一个公开的值。

1.2 认证

双方都通过Confirmation Key 、RandomDevice 和 Auth Value三个参数生成认证值。配网器生成随机数,然后通过认证密钥和AuthValue共同生成认证值,把认证值发给未配网设备,然后再发获得配网器的认证值保存下来,并进入到向配网器发送认证值阶段,发送认证值之前也要生成随机数,与认证密钥和AuthValue生成未配网设备认证值,并先进行认证值比较,如果相等,此时发送。

双方确认值计算方法

1.3 建立对话

会话密钥和会话一次性数字

2. 设备密钥

设备密钥是在配网过程中生成,只有节点和配置客户端知道的访问层密钥。设备密钥是一个特殊的应用密钥。

设备密钥

3. 应用密钥

应用密钥是通过控制器里的随机数生成器生成。应用密钥是配网器通过自己生成的随机数生成的。它用于加密上层传输层中的消息,如服务器模型与客户端模型绑定的应用密钥不一致,则无法进行通信。

应用ID生成 应用密钥绑定实例

4. 网络密钥

网络密钥是由控制器里的随机数生成器生成,占16个字节,用于加密网络层消息,具有相同网络密钥的节点视为同一网络。

  • NetWork ID:占8个字节,NetWork ID来自于网络密钥,这样每个网络密钥就会生成一个网络ID。此标识符将成为公共信息。
  • NID:占7个bit,用于标识用于保护此网络PDU,每个NID最多有2121个可能的密钥,用来标识验证此PDU的EncryptionKey 和 PrivacyKey。
  • EncryptionKey:加密密钥,网络层传输数据时用的加密密钥,占16个字节。
  • PrivacyKey:私有密钥,占16个字节。
  • IdentityKey:标识密钥,占16个字节。用于支持GATT代理服务。
  • BeaconKey:Beacon密钥来自于网络密钥,这样每个网络密钥就会生成一个Beacon密钥。
网络密钥派生

二、代码分析验证

1. mesh_crypto.h

文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/inc/mesh_crypto.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// 生成只能被使用一次的随机值
static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
size_t len, u8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };

return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
// s1函数 通过字符串输入生成一个一次性随机值 salt ,用作生成其它密钥的佐料
static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
{
const u8_t zero[16] = { 0 };

return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
}

int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
const char *info, u8_t okm[16]);

#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
({ \
const u8_t salt[16] = salt_str; \
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
})

int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);

int bt_mesh_k3(const u8_t n[16], u8_t out[8]);

int bt_mesh_k4(const u8_t n[16], u8_t out[1]);

// 标识密钥生成被调用
int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);

static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
u8_t resolving_key[16])
{
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
}
// 标识密钥
static inline int bt_mesh_identity_key(const u8_t net_key[16],
u8_t identity_key[16])
{
return bt_mesh_id128(net_key, "nkik", identity_key);
}
// 信标密钥
static inline int bt_mesh_beacon_key(const u8_t net_key[16],
u8_t beacon_key[16])
{
return bt_mesh_id128(net_key, "nkbk", beacon_key);
}
// 信标认证
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
const u8_t net_id[16], u32_t iv_index,
u8_t auth[8]);
// 应用ID
static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
{
return bt_mesh_k4(app_key, app_id);
}
// 会话密钥
static inline int bt_mesh_session_key(const u8_t dhkey[32],
const u8_t prov_salt[16],
u8_t session_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
}
// 会话一次性密钥
static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
const u8_t prov_salt[16],
u8_t nonce[13])
{
u8_t tmp[16];
int err;

err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
if (!err) {
memcpy(nonce, tmp + 3, 13);
}

return err;
}
// 设备密钥
static inline int bt_mesh_dev_key(const u8_t dhkey[32],
const u8_t prov_salt[16],
u8_t dev_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
}
// 配网过程“佐料”
static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
const u8_t prov_rand[16],
const u8_t dev_rand[16],
u8_t prov_salt[16])
{
const u8_t prov_salt_key[16] = { 0 };
struct bt_mesh_sg sg[] = {
{ conf_salt, 16 },
{ prov_rand, 16 },
{ dev_rand, 16 },
};

return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
}

int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
const u8_t privacy_key[16]);
// 网络层加密(网络层调用)
int bt_mesh_net_encrypt(const u8_t key[16], struct net_buf_simple *buf,
u32_t iv_index, bool proxy);
// 网络层解码(网络层调用)
int bt_mesh_net_decrypt(const u8_t key[16], struct net_buf_simple *buf,
u32_t iv_index, bool proxy);
// 应用层加密(传输层调用)
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
struct net_buf_simple *buf, const u8_t *ad,
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
// 应用层解码(传输层调用)
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
struct net_buf_simple *buf, struct net_buf_simple *out,
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
u32_t iv_index);

// FCS - Frame Check Sequence 帧校验序列生成(PB-ADV 广播包调用)
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);

// FCS - Frame Check Sequence 帧校验序列检查(PB-ADV 广播包调用)
bool bt_mesh_fcs_check(struct net_buf_simple *buf, u8_t received_fcs);

// 虚拟组播地址生成
int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);

// 通过配网过程输入数据生成认证“佐料”
int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);

// 认证密钥生成
int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
u8_t conf_key[16]);

// 生成确认值(配网第4阶段 - 身份认证)
int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
const u8_t auth[16], u8_t conf[16]);

// 配网数据加密(配网第5阶段 - 分发数据阶段)
int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
const u8_t data[25 + 8], u8_t out[25]);



2. net.c

文件路径:genie-bt-mesh-stack-master/network/bluetooth/bt_mesh/src/net.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//网络密钥创建
int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
const u8_t key[16])
{
u8_t p[] = { 0 };
u8_t nid;
int err;
//通过分配的网络密钥生成NID、加密密钥、私有密钥
err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
if (err) {
BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
return err;
}

memcpy(keys->net, key, 16);

keys->nid = nid;

BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));

err = bt_mesh_k3(key, keys->net_id);
if (err) {
BT_ERR("Unable to generate Net ID");
return err;
}

BT_DBG("NetID %s", bt_hex(keys->net_id, 8));

#if defined(CONFIG_BT_MESH_GATT_PROXY)
// 标识密钥生成
err = bt_mesh_identity_key(key, keys->identity);
if (err) {
BT_ERR("Unable to generate IdentityKey");
return err;
}

BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
#endif /* GATT_PROXY */

// 信标密钥生成
err = bt_mesh_beacon_key(key, keys->beacon);
if (err) {
BT_ERR("Unable to generate beacon key");
return err;
}

BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));

return 0;
}