1 /*
2 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <genie_provision.h>
8 #include "genie_service.h"
9
10 #ifdef GENIE_ULTRA_PROV
11 #include <errno.h>
12 #include <tinycrypt/sha256.h>
13 #include <tinycrypt/constants.h>
14
15 #include <net/buf.h>
16 #include "crypto.h"
17 #include "adv.h"
18
19 #define BUF_TIMEOUT K_MSEC(400)
20 #define BT_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf))
21
22 static uint8_t p_prov_data_key[32];
23 static uint8_t p_ultra_prov_devkey[32];
24 static uint8_t p_confirm[16];
25 #endif
26
27 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
28 #include "common/log.h"
29
30 static struct k_timer pbadv_timeout_timer;
31 static struct k_timer prov_timeout_timer;
32
33 static genie_provision_state_e provision_state = GENIE_PROVISION_UNPROV;
34 static uint8_t genie_uuid[GENIE_PROVISON_UUID_LEN];
35
genie_provision_set_silent_flag(void)36 static void genie_provision_set_silent_flag(void)
37 {
38 genie_uuid[13] |= UNPROV_ADV_FEATURE1_SILENT_ADV;
39 }
40
genie_provision_clear_silent_flag(void)41 void genie_provision_clear_silent_flag(void)
42 {
43 genie_uuid[13] &= UNPROV_ADV_FEATURE1_SILENT_UNMASK;
44 }
45
genie_provision_set_state(genie_provision_state_e state)46 int genie_provision_set_state(genie_provision_state_e state)
47 {
48 provision_state = state;
49
50 return 0;
51 }
52
genie_provision_get_state(void)53 genie_provision_state_e genie_provision_get_state(void)
54 {
55 return provision_state;
56 }
57
genie_provision_get_uuid(void)58 uint8_t *genie_provision_get_uuid(void)
59 {
60 int i = 0;
61 genie_triple_t *p_genie_triple = NULL;
62
63 p_genie_triple = genie_triple_get();
64
65 // all fields in uuid should be in little-endian
66 // CID: Taobao
67 genie_uuid[0] = CONFIG_MESH_VENDOR_COMPANY_ID & 0xFF;
68 genie_uuid[1] = (CONFIG_MESH_VENDOR_COMPANY_ID >> 8) & 0xFF;
69
70 // PID
71 // Bit0~Bit3: 0001 (broadcast version)
72 // Bit4:1 (one secret pre device)
73 // Bit5: 1 (OTA support)
74 // Bit6~Bit7: 01 (00:4.0 01:4.2 10:5.0 11:>5.0)
75 genie_uuid[2] = 0x71;
76
77 // Product ID
78 for (i = 0; i < 4; i++)
79 {
80 genie_uuid[3 + i] = (p_genie_triple->pid >> (i << 3)) & 0xFF;
81 }
82
83 // mac addr (device name)
84 for (i = 0; i < GENIE_TRIPLE_MAC_SIZE; i++)
85 {
86 genie_uuid[7 + i] = p_genie_triple->mac[GENIE_TRIPLE_MAC_SIZE - 1 - i];
87 }
88
89 genie_uuid[13] = UNPROV_ADV_FEATURE1_UUID_VERSION;
90
91 #if defined(BOARD_TG7100B)
92 genie_uuid[14] = UNPROV_ADV_FEATURE2_GENIE_MESH_STACK_V1;
93 #elif defined(BOARD_PHY6220_EVB) || defined(BOARD_TG7120B_EVB)
94 genie_uuid[14] = UNPROV_ADV_FEATURE2_GENIE_MESH_STACK_V2;
95 #elif defined(BOARD_TG7121B_EVB)
96 genie_uuid[14] = UNPROV_ADV_FEATURE2_GENIE_MESH_STACK_V3;
97 #endif
98
99 #ifdef GENIE_ULTRA_PROV
100 genie_uuid[14] |= UNPROV_ADV_FEATURE2_ULTRA_PROV_FLAG;
101 genie_uuid[14] |= UNPROV_ADV_FEATURE2_AUTH_FLAG;
102 #else
103 #ifndef GENIE_OLD_AUTH
104 genie_uuid[14] |= UNPROV_ADV_FEATURE2_AUTH_FLAG;
105 #endif
106 #endif
107
108 BT_INFO("uuid: %s", bt_hex(genie_uuid, GENIE_PROVISON_UUID_LEN));
109
110 return genie_uuid;
111 }
112
genie_provision_get_saved_data(genie_provision_t * p_genie_provision)113 int genie_provision_get_saved_data(genie_provision_t *p_genie_provision)
114 {
115 genie_storage_status_e ret = GENIE_STORAGE_SUCCESS;
116
117 if (p_genie_provision == NULL)
118 {
119 return -1;
120 }
121
122 memset(p_genie_provision, 0, sizeof(genie_provision_t));
123
124 ret = genie_storage_read_addr(&p_genie_provision->addr);
125 if (ret != GENIE_STORAGE_SUCCESS)
126 {
127 return ret;
128 }
129
130 ret = genie_storage_read_seq(&p_genie_provision->seq);
131 if (ret != GENIE_STORAGE_SUCCESS)
132 {
133 return ret;
134 }
135
136 ret = genie_storage_read_devkey(p_genie_provision->devkey);
137 if (ret != GENIE_STORAGE_SUCCESS)
138 {
139 return ret;
140 }
141
142 ret = genie_storage_read_netkey(&p_genie_provision->netkey);
143 if (ret != GENIE_STORAGE_SUCCESS)
144 {
145 return ret;
146 }
147
148 ret = genie_storage_read_appkey(&p_genie_provision->appkey);
149 if (ret != GENIE_STORAGE_SUCCESS)
150 {
151 return ret;
152 }
153
154 return 0;
155 }
156
157 #ifdef GENIE_ULTRA_PROV
ultra_prov_get_auth(const uint8_t random_hex[16],const uint8_t key[16],uint8_t cfm[16])158 void ultra_prov_get_auth(const uint8_t random_hex[16], const uint8_t key[16], uint8_t cfm[16])
159 {
160 bt_mesh_prov_conf(key, random_hex, genie_crypto_get_auth(random_hex), cfm);
161
162 BT_DBG("cfm: %s", bt_hex(cfm, 16));
163 }
164
_ultra_prov_send(uint8_t type,uint8_t * p_msg,uint8_t len)165 static int _ultra_prov_send(uint8_t type, uint8_t *p_msg, uint8_t len)
166 {
167 struct net_buf *buf;
168
169 buf = bt_mesh_adv_create(0, 0, BUF_TIMEOUT);
170 if (!buf)
171 {
172 BT_ERR("Out of provisioning buffers");
173 return -ENOBUFS;
174 }
175
176 BT_MESH_ADV(buf)->tiny_adv = 1;
177
178 net_buf_add_be16(buf, CONFIG_MESH_VENDOR_COMPANY_ID);
179 //VID
180 net_buf_add_u8(buf, 0x0d);
181 net_buf_add_u8(buf, type);
182 net_buf_add_mem(buf, p_msg, len);
183
184 BT_DBG("send %s", bt_hex(buf->data, buf->len));
185
186 bt_mesh_adv_send(buf, NULL, NULL);
187 net_buf_unref(buf);
188
189 return 0;
190 }
191
genie_provision_ultra_prov_recv_random(uint8_t * buf)192 static void genie_provision_ultra_prov_recv_random(uint8_t *buf)
193 {
194 uint8_t tmp[48];
195 uint8_t random_a[17];
196 uint8_t random_b[17];
197 uint8_t cfm_key[32];
198
199 int ret;
200 struct tc_sha256_state_struct sha256_ctx;
201 genie_triple_t *p_genie_triple = genie_triple_get();
202
203 if (buf[0] != p_genie_triple->mac[4] || buf[1] != p_genie_triple->mac[5])
204 {
205 return;
206 }
207 buf += 2;
208
209 genie_event(GENIE_EVT_SDK_MESH_PROV_START, NULL);
210
211 memset(p_prov_data_key, 0, sizeof(p_prov_data_key));
212 memset(p_ultra_prov_devkey, 0, sizeof(p_ultra_prov_devkey));
213 memset(p_confirm, 0, sizeof(p_confirm));
214
215 hextostring(buf, (char *)random_a, 8);
216 random_a[16] = 0;
217 hextostring(buf + 8, (char *)random_b, 8);
218 random_b[16] = 0;
219
220 sprintf((char *)tmp, "%s%sConfirmationKey", random_a, random_b);
221
222 BT_DBG("string %s\n", tmp);
223
224 /* calculate the sha256 of random and
225 * fetch the top 16 bytes as confirmationKey
226 */
227 ret = tc_sha256_init(&sha256_ctx);
228 if (ret != TC_CRYPTO_SUCCESS)
229 {
230 BT_ERR("sha256 init fail\n");
231 }
232
233 ret = tc_sha256_update(&sha256_ctx, tmp, 47);
234 if (ret != TC_CRYPTO_SUCCESS)
235 {
236 BT_ERR("sha256 udpate fail\n");
237 }
238
239 ret = tc_sha256_final(cfm_key, &sha256_ctx);
240 if (ret != TC_CRYPTO_SUCCESS)
241 {
242 BT_ERR("sha256 final fail\n");
243 }
244 else
245 {
246 BT_DBG("cfmKey: %s", bt_hex(cfm_key, 16));
247 }
248
249 //calc cloud cfm
250 memcpy(tmp, buf + 8, 8);
251 memcpy(tmp + 8, buf, 8);
252 ultra_prov_get_auth(tmp, cfm_key, p_confirm);
253
254 hextostring(p_confirm, (char *)tmp, 16);
255 sprintf((char *)tmp + 32, "SessionKey");
256 BT_DBG("tmp %s\n", tmp);
257 ret = tc_sha256_init(&sha256_ctx);
258 if (ret != TC_CRYPTO_SUCCESS)
259 {
260 BT_ERR("sha256 init fail\n");
261 }
262
263 ret = tc_sha256_update(&sha256_ctx, tmp, 42);
264 if (ret != TC_CRYPTO_SUCCESS)
265 {
266 BT_ERR("sha256 udpate fail\n");
267 }
268
269 ret = tc_sha256_final(p_prov_data_key, &sha256_ctx);
270 if (ret != TC_CRYPTO_SUCCESS)
271 {
272 BT_ERR("sha256 final fail\n");
273 }
274 else
275 {
276 BT_DBG("provKkey: %s", bt_hex(p_prov_data_key, 22));
277 }
278
279 //calc dev key
280 sprintf((char *)tmp + 32, "DeviceKey");
281 BT_DBG("tmp %s\n", tmp);
282 ret = tc_sha256_init(&sha256_ctx);
283 if (ret != TC_CRYPTO_SUCCESS)
284 {
285 BT_ERR("sha256 init fail\n");
286 }
287
288 ret = tc_sha256_update(&sha256_ctx, tmp, 41);
289 if (ret != TC_CRYPTO_SUCCESS)
290 {
291 BT_ERR("sha256 udpate fail\n");
292 }
293
294 ret = tc_sha256_final(p_ultra_prov_devkey, &sha256_ctx);
295 if (ret != TC_CRYPTO_SUCCESS)
296 {
297 BT_ERR("sha256 final fail\n");
298 }
299 else
300 {
301 BT_INFO("dk %s", bt_hex(p_ultra_prov_devkey, 16));
302 }
303
304 memcpy(tmp, buf, 16);
305 ultra_prov_get_auth(tmp, cfm_key, p_confirm);
306
307 tmp[0] = p_genie_triple->mac[4];
308 tmp[1] = p_genie_triple->mac[5];
309 memcpy(tmp + 2, p_confirm, 16);
310
311 _ultra_prov_send(GENIE_PROV_STATUS_SEND_CONFIRM_DATA, tmp, 18);
312 }
313
genie_provision_ultra_prov_recv_data(uint8_t * buf)314 static void genie_provision_ultra_prov_recv_data(uint8_t *buf)
315 {
316 uint8_t i = 0;
317 uint16_t net_idx;
318 uint8_t flags;
319 uint32_t iv_index;
320 uint16_t addr;
321 genie_triple_t *p_genie_triple = genie_triple_get();
322
323 if (genie_provision_get_state() != GENIE_PROVISION_START)
324 {
325 BT_WARN("I not in provisioning");
326 return;
327 }
328
329 while (i < 22)
330 {
331 buf[i] ^= p_prov_data_key[i];
332 i++;
333 }
334 BT_DBG("%s", bt_hex(buf, 22));
335
336 if (buf[0] != p_genie_triple->mac[4] || buf[1] != p_genie_triple->mac[5])
337 {
338 return;
339 }
340 buf += 2;
341
342 flags = buf[0];
343 net_idx = 0;
344 iv_index = buf[17];
345 addr = sys_get_be16(&buf[18]);
346
347 BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
348 net_idx, iv_index, addr);
349
350 genie_event(GENIE_EVT_SDK_MESH_PROV_DATA, &addr);
351 BT_INFO("nk %s", bt_hex(buf + 1, 16));
352 bt_mesh_provision(buf + 1, net_idx, flags, iv_index, addr, p_ultra_prov_devkey);
353
354 _ultra_prov_send(GENIE_PROV_STATUS_SEND_COMPLETED, p_genie_triple->mac, 6);
355 }
356
genie_provision_ultra_prov_handle(uint8_t frame_type,void * frame_buf)357 int genie_provision_ultra_prov_handle(uint8_t frame_type, void *frame_buf)
358 {
359 uint16_t company = 0;
360 uint8_t fixed_byte = 0;
361 uint8_t prov_cmd = 0;
362 struct net_buf_simple *buf = NULL;
363
364 buf = (struct net_buf_simple *)frame_buf;
365 if (frame_type != GENIE_PROV_ADV_TYPE || buf == NULL)
366 {
367 return -1;
368 }
369
370 company = net_buf_simple_pull_be16(buf);
371 if (company == CONFIG_MESH_VENDOR_COMPANY_ID)
372 {
373 fixed_byte = net_buf_simple_pull_u8(buf);
374 if (fixed_byte == GENIE_PROV_FIXED_BYTE)
375 {
376 prov_cmd = net_buf_simple_pull_u8(buf);
377 switch (prov_cmd)
378 {
379 case GENIE_PROV_STATUS_RECV_RANDOM:
380 genie_provision_ultra_prov_recv_random(buf->data);
381 break;
382 case GENIE_PROV_STATUS_RECV_PROV_DATA:
383 genie_provision_ultra_prov_recv_data(buf->data);
384 break;
385 default:
386 break;
387 }
388 }
389 }
390
391 return 0;
392 }
393 #endif
394
_genie_pbadv_timer_cb(void * p_timer,void * args)395 static void _genie_pbadv_timer_cb(void *p_timer, void *args)
396 {
397 genie_event(GENIE_EVT_SDK_MESH_PBADV_TIMEOUT, NULL);
398 }
399
genie_provision_pbadv_timer_start(uint32_t prov_timeout)400 void genie_provision_pbadv_timer_start(uint32_t prov_timeout)
401 {
402 static uint8_t inited = 0;
403
404 if (!inited)
405 {
406 k_timer_init(&pbadv_timeout_timer, _genie_pbadv_timer_cb, NULL);
407 inited = 1;
408 }
409
410 k_timer_start(&pbadv_timeout_timer, prov_timeout);
411 }
412
genie_provision_pbadv_timer_stop(void)413 void genie_provision_pbadv_timer_stop(void)
414 {
415 k_timer_stop(&pbadv_timeout_timer);
416 }
417
genie_provision_start_slient_pbadv(void)418 void genie_provision_start_slient_pbadv(void)
419 {
420 genie_provision_set_silent_flag();
421 //bt_mesh_prov_disable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
422 extern void genie_set_silent_unprov_beacon_interval(bool is_silent);
423 genie_set_silent_unprov_beacon_interval(true);
424 bt_mesh_prov_enable(BT_MESH_PROV_ADV);
425 }
426
_genie_prov_timer_cb(void * p_timer,void * args)427 static void _genie_prov_timer_cb(void *p_timer, void *args)
428 {
429 genie_event(GENIE_EVT_SDK_MESH_PROV_TIMEOUT, NULL);
430 }
431
genie_provision_prov_timer_start(void)432 void genie_provision_prov_timer_start(void)
433 {
434 static uint8_t inited = 0;
435
436 if (!inited)
437 {
438 k_timer_init(&prov_timeout_timer, _genie_prov_timer_cb, NULL);
439 inited = 1;
440 }
441 k_timer_start(&prov_timeout_timer, MESH_PROVISIONING_TIMEOUT);
442 }
443
genie_provision_prov_timer_stop(void)444 void genie_provision_prov_timer_stop(void)
445 {
446 k_timer_stop(&prov_timeout_timer);
447 }
448