1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2020 Lingao Meng
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <errno.h>
10 #include <zephyr/sys/atomic.h>
11 #include <zephyr/sys/util.h>
12 #include <zephyr/sys/byteorder.h>
13 
14 #include <zephyr/net/buf.h>
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/mesh.h>
18 #include <zephyr/bluetooth/uuid.h>
19 
20 #include "crypto.h"
21 #include "mesh.h"
22 #include "net.h"
23 #include "access.h"
24 #include "foundation.h"
25 #include "prov.h"
26 
27 #define LOG_LEVEL CONFIG_BT_MESH_PROV_LOG_LEVEL
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(bt_mesh_prov);
30 
31 struct bt_mesh_prov_link bt_mesh_prov_link;
32 const struct bt_mesh_prov *bt_mesh_prov;
33 
34 /* Verify specification defined length: */
35 BUILD_ASSERT(sizeof(bt_mesh_prov_link.conf_inputs) == 145,
36 	     "Confirmation inputs shall be 145 bytes");
37 
bt_mesh_prov_reset_state(void)38 int bt_mesh_prov_reset_state(void)
39 {
40 	int err;
41 	const size_t offset = offsetof(struct bt_mesh_prov_link, auth);
42 
43 	atomic_clear(bt_mesh_prov_link.flags);
44 	(void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0,
45 		     sizeof(bt_mesh_prov_link) - offset);
46 
47 	err = bt_mesh_pub_key_gen();
48 	if (err) {
49 		LOG_ERR("Failed to generate public key (%d)", err);
50 		return err;
51 	}
52 	return 0;
53 }
54 
output_action(uint8_t action)55 static bt_mesh_output_action_t output_action(uint8_t action)
56 {
57 	switch (action) {
58 	case OUTPUT_OOB_BLINK:
59 		return BT_MESH_BLINK;
60 	case OUTPUT_OOB_BEEP:
61 		return BT_MESH_BEEP;
62 	case OUTPUT_OOB_VIBRATE:
63 		return BT_MESH_VIBRATE;
64 	case OUTPUT_OOB_NUMBER:
65 		return BT_MESH_DISPLAY_NUMBER;
66 	case OUTPUT_OOB_STRING:
67 		return BT_MESH_DISPLAY_STRING;
68 	default:
69 		return BT_MESH_NO_OUTPUT;
70 	}
71 }
72 
input_action(uint8_t action)73 static bt_mesh_input_action_t input_action(uint8_t action)
74 {
75 	switch (action) {
76 	case INPUT_OOB_PUSH:
77 		return BT_MESH_PUSH;
78 	case INPUT_OOB_TWIST:
79 		return BT_MESH_TWIST;
80 	case INPUT_OOB_NUMBER:
81 		return BT_MESH_ENTER_NUMBER;
82 	case INPUT_OOB_STRING:
83 		return BT_MESH_ENTER_STRING;
84 	default:
85 		return BT_MESH_NO_INPUT;
86 	}
87 }
88 
check_output_auth(bt_mesh_output_action_t output,uint8_t size)89 static int check_output_auth(bt_mesh_output_action_t output, uint8_t size)
90 {
91 	if (!output) {
92 		return -EINVAL;
93 	}
94 
95 	if (!(bt_mesh_prov->output_actions & output)) {
96 		return -EINVAL;
97 	}
98 
99 	if (size > bt_mesh_prov->output_size) {
100 		return -EINVAL;
101 	}
102 
103 	return 0;
104 }
105 
check_input_auth(bt_mesh_input_action_t input,uint8_t size)106 static int check_input_auth(bt_mesh_input_action_t input, uint8_t size)
107 {
108 	if (!input) {
109 		return -EINVAL;
110 	}
111 
112 	if (!(bt_mesh_prov->input_actions & input)) {
113 		return -EINVAL;
114 	}
115 
116 	if (size > bt_mesh_prov->input_size) {
117 		return -EINVAL;
118 	}
119 
120 	return 0;
121 }
122 
get_auth_string(char * str,uint8_t size)123 static void get_auth_string(char *str, uint8_t size)
124 {
125 	uint64_t value;
126 
127 	bt_rand(&value, sizeof(value));
128 
129 	static const char characters[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
130 
131 	for (int i = 0; i < size; i++) {
132 		/* pull base-36 digits: */
133 		int idx = value % 36;
134 
135 		value = value / 36;
136 		str[i] = characters[idx];
137 	}
138 
139 	str[size] = '\0';
140 
141 	memcpy(bt_mesh_prov_link.auth, str, size);
142 	memset(bt_mesh_prov_link.auth + size, 0,
143 			sizeof(bt_mesh_prov_link.auth) - size);
144 }
145 
get_auth_number(bt_mesh_output_action_t output,bt_mesh_input_action_t input,uint8_t size)146 static uint32_t get_auth_number(bt_mesh_output_action_t output,
147 		bt_mesh_input_action_t input, uint8_t size)
148 {
149 	const uint32_t divider[PROV_IO_OOB_SIZE_MAX] = { 10, 100, 1000, 10000,
150 			100000, 1000000, 10000000, 100000000 };
151 	uint8_t auth_size = bt_mesh_prov_auth_size_get();
152 	uint32_t num = 0;
153 
154 	bt_rand(&num, sizeof(num));
155 
156 	if (output == BT_MESH_BLINK ||
157 	    output == BT_MESH_BEEP ||
158 	    output == BT_MESH_VIBRATE ||
159 	    input == BT_MESH_PUSH ||
160 	    input == BT_MESH_TWIST) {
161 		/* According to the Bluetooth Mesh Profile
162 		 * Specification Section 5.4.2.4, blink, beep
163 		 * vibrate, push and twist should be a random integer
164 		 * between 0 and 10^size, *exclusive*:
165 		 */
166 		num = (num % (divider[size - 1] - 1)) + 1;
167 	} else {
168 		num %= divider[size - 1];
169 	}
170 
171 	sys_put_be32(num, &bt_mesh_prov_link.auth[auth_size - sizeof(num)]);
172 	memset(bt_mesh_prov_link.auth, 0, auth_size - sizeof(num));
173 
174 	return num;
175 }
176 
bt_mesh_prov_auth(bool is_provisioner,uint8_t method,uint8_t action,uint8_t size)177 int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size)
178 {
179 	bt_mesh_output_action_t output;
180 	bt_mesh_input_action_t input;
181 	uint8_t auth_size = bt_mesh_prov_auth_size_get();
182 	int err;
183 
184 	if (IS_ENABLED(CONFIG_BT_MESH_OOB_AUTH_REQUIRED) &&
185 	    (method == AUTH_METHOD_NO_OOB ||
186 	    bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM)) {
187 		return -EINVAL;
188 	}
189 
190 	switch (method) {
191 	case AUTH_METHOD_NO_OOB:
192 		if (action || size) {
193 			return -EINVAL;
194 		}
195 
196 		(void)memset(bt_mesh_prov_link.auth, 0, auth_size);
197 		return 0;
198 	case AUTH_METHOD_STATIC:
199 		if (action || size) {
200 			return -EINVAL;
201 		}
202 
203 		atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY);
204 
205 		return 0;
206 
207 	case AUTH_METHOD_OUTPUT:
208 		output = output_action(action);
209 
210 		if (is_provisioner) {
211 			if (output == BT_MESH_DISPLAY_STRING) {
212 				input = BT_MESH_ENTER_STRING;
213 				atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING);
214 			} else {
215 				input = BT_MESH_ENTER_NUMBER;
216 				atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER);
217 			}
218 
219 			return bt_mesh_prov->input(input, size);
220 		}
221 
222 		err = check_output_auth(output, size);
223 		if (err) {
224 			return err;
225 		}
226 
227 		if (output == BT_MESH_DISPLAY_STRING) {
228 			char str[9];
229 
230 			atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
231 			get_auth_string(str, size);
232 			return bt_mesh_prov->output_string(str);
233 		}
234 
235 		atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
236 		return bt_mesh_prov->output_number(output,
237 				get_auth_number(output, BT_MESH_NO_INPUT, size));
238 
239 	case AUTH_METHOD_INPUT:
240 		input = input_action(action);
241 
242 		if (!is_provisioner) {
243 			err = check_input_auth(input, size);
244 			if (err) {
245 				return err;
246 			}
247 
248 			if (input == BT_MESH_ENTER_STRING) {
249 				atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING);
250 			} else {
251 				atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER);
252 			}
253 
254 			return bt_mesh_prov->input(input, size);
255 		}
256 
257 		if (input == BT_MESH_ENTER_STRING) {
258 			char str[9];
259 
260 			atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
261 			get_auth_string(str, size);
262 			return bt_mesh_prov->output_string(str);
263 		}
264 
265 		atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
266 		output = BT_MESH_DISPLAY_NUMBER;
267 		return bt_mesh_prov->output_number(output,
268 				get_auth_number(BT_MESH_NO_OUTPUT, input, size));
269 
270 	default:
271 		return -EINVAL;
272 	}
273 }
274 
bt_mesh_input_number(uint32_t num)275 int bt_mesh_input_number(uint32_t num)
276 {
277 	uint8_t auth_size = bt_mesh_prov_auth_size_get();
278 
279 	LOG_DBG("%u", num);
280 
281 	if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) {
282 		return -EINVAL;
283 	}
284 
285 	sys_put_be32(num, &bt_mesh_prov_link.auth[auth_size - sizeof(num)]);
286 
287 	bt_mesh_prov_link.role->input_complete();
288 
289 	return 0;
290 }
291 
bt_mesh_input_string(const char * str)292 int bt_mesh_input_string(const char *str)
293 {
294 	LOG_DBG("%s", str);
295 
296 	if (strlen(str) > PROV_IO_OOB_SIZE_MAX ||
297 			strlen(str) > bt_mesh_prov_link.oob_size) {
298 		return -ENOTSUP;
299 	}
300 
301 	if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
302 		return -EINVAL;
303 	}
304 
305 	memcpy(bt_mesh_prov_link.auth, str, strlen(str));
306 
307 	bt_mesh_prov_link.role->input_complete();
308 
309 	return 0;
310 }
311 
bt_mesh_prov_get(void)312 const struct bt_mesh_prov *bt_mesh_prov_get(void)
313 {
314 	return bt_mesh_prov;
315 }
316 
bt_mesh_prov_active(void)317 bool bt_mesh_prov_active(void)
318 {
319 	return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
320 }
321 
prov_recv(const struct prov_bearer * bearer,void * cb_data,struct net_buf_simple * buf)322 static void prov_recv(const struct prov_bearer *bearer, void *cb_data,
323 		      struct net_buf_simple *buf)
324 {
325 	static const uint8_t op_len[10] = {
326 		[PROV_INVITE]         = PDU_LEN_INVITE,
327 		[PROV_CAPABILITIES]   = PDU_LEN_CAPABILITIES,
328 		[PROV_START]          = PDU_LEN_START,
329 		[PROV_PUB_KEY]        = PDU_LEN_PUB_KEY,
330 		[PROV_INPUT_COMPLETE] = PDU_LEN_INPUT_COMPLETE,
331 		[PROV_CONFIRM]        = PDU_LEN_CONFIRM,
332 		[PROV_RANDOM]         = PDU_LEN_RANDOM,
333 		[PROV_DATA]           = PDU_LEN_DATA,
334 		[PROV_COMPLETE]       = PDU_LEN_COMPLETE,
335 		[PROV_FAILED]         = PDU_LEN_FAILED,
336 	};
337 
338 	uint8_t type = buf->data[0];
339 
340 	LOG_DBG("type 0x%02x len %u", type, buf->len);
341 
342 	if (type >= ARRAY_SIZE(bt_mesh_prov_link.role->op)) {
343 		LOG_ERR("Unknown provisioning PDU type 0x%02x", type);
344 		bt_mesh_prov_link.role->error(PROV_ERR_NVAL_PDU);
345 		return;
346 	}
347 
348 	if ((type != PROV_FAILED && type != bt_mesh_prov_link.expect) ||
349 	    !bt_mesh_prov_link.role->op[type]) {
350 		LOG_WRN("Unexpected msg 0x%02x != 0x%02x", type, bt_mesh_prov_link.expect);
351 		bt_mesh_prov_link.role->error(PROV_ERR_UNEXP_PDU);
352 		return;
353 	}
354 
355 	uint8_t expected = 1 + op_len[type];
356 
357 	if (type == PROV_CONFIRM || type == PROV_RANDOM) {
358 		/* Expected length depends on Auth size */
359 		expected = 1 + bt_mesh_prov_auth_size_get();
360 	}
361 
362 	if (buf->len != expected) {
363 		LOG_ERR("Invalid length %u for type 0x%02x", buf->len, type);
364 		bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
365 		return;
366 	}
367 
368 	bt_mesh_prov_link.role->op[type](&buf->data[1]);
369 }
370 
prov_link_opened(const struct prov_bearer * bearer,void * cb_data)371 static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data)
372 {
373 	atomic_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
374 
375 	if (bt_mesh_prov->link_open) {
376 		bt_mesh_prov->link_open(bearer->type);
377 	}
378 
379 	bt_mesh_prov_link.bearer = bearer;
380 
381 	if (bt_mesh_prov_link.role->link_opened) {
382 		bt_mesh_prov_link.role->link_opened();
383 	}
384 }
385 
prov_link_closed(const struct prov_bearer * bearer,void * cb_data,enum prov_bearer_link_status reason)386 static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data,
387 			     enum prov_bearer_link_status reason)
388 {
389 	LOG_DBG("%u", reason);
390 
391 	if (bt_mesh_prov_link.role->link_closed) {
392 		bt_mesh_prov_link.role->link_closed(reason);
393 	}
394 
395 	if (bt_mesh_prov->link_close) {
396 		bt_mesh_prov->link_close(bearer->type);
397 	}
398 }
399 
prov_bearer_error(const struct prov_bearer * bearer,void * cb_data,uint8_t err)400 static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data,
401 			      uint8_t err)
402 {
403 	if (bt_mesh_prov_link.role->error) {
404 		bt_mesh_prov_link.role->error(err);
405 	}
406 }
407 
408 static const struct prov_bearer_cb prov_bearer_cb = {
409 	.link_opened = prov_link_opened,
410 	.link_closed = prov_link_closed,
411 	.error = prov_bearer_error,
412 	.recv = prov_recv,
413 };
414 
bt_mesh_prov_bearer_cb_get(void)415 const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void)
416 {
417 	return &prov_bearer_cb;
418 }
419 
bt_mesh_prov_complete(uint16_t net_idx,uint16_t addr)420 void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr)
421 {
422 	if (bt_mesh_prov->complete) {
423 		bt_mesh_prov->complete(net_idx, addr);
424 	}
425 }
426 
bt_mesh_prov_reset(void)427 void bt_mesh_prov_reset(void)
428 {
429 	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
430 		bt_mesh_pb_adv_reset();
431 	}
432 
433 	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
434 		bt_mesh_pb_gatt_reset();
435 	}
436 
437 	bt_mesh_prov_reset_state();
438 
439 	if (bt_mesh_prov->reset) {
440 		bt_mesh_prov->reset();
441 	}
442 }
443 
bt_mesh_prov_init(const struct bt_mesh_prov * prov_info)444 int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
445 {
446 	if (!prov_info) {
447 		LOG_ERR("No provisioning context provided");
448 		return -EINVAL;
449 	}
450 
451 	bt_mesh_prov = prov_info;
452 
453 	if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
454 		bt_mesh_pb_adv_init();
455 	}
456 
457 	if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
458 		bt_mesh_pb_gatt_init();
459 	}
460 
461 	return bt_mesh_prov_reset_state();
462 }
463