1 /*
2  * Copyright (c) 2017 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/hci_types.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/sys/__assert.h>
17 #include <zephyr/sys/atomic.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/check.h>
20 #include <zephyr/bluetooth/hci.h>
21 #include <zephyr/logging/log.h>
22 #include <zephyr/sys/slist.h>
23 #include <zephyr/sys/util_macro.h>
24 #include <psa/crypto.h>
25 #include <psa/crypto_struct.h>
26 #include <psa/crypto_types.h>
27 #include <psa/crypto_values.h>
28 
29 #include "long_wq.h"
30 #include "ecc.h"
31 #include "hci_core.h"
32 
33 #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
34 LOG_MODULE_REGISTER(bt_ecc);
35 
36 static uint8_t pub_key[BT_PUB_KEY_LEN];
37 static sys_slist_t pub_key_cb_slist;
38 static bt_dh_key_cb_t dh_key_cb;
39 
40 static void generate_pub_key(struct k_work *work);
41 static void generate_dh_key(struct k_work *work);
42 K_WORK_DEFINE(pub_key_work, generate_pub_key);
43 K_WORK_DEFINE(dh_key_work, generate_dh_key);
44 
45 enum {
46 	PENDING_PUB_KEY,
47 	PENDING_DHKEY,
48 
49 	/* Total number of flags - must be at the end of the enum */
50 	NUM_FLAGS,
51 };
52 
53 static ATOMIC_DEFINE(flags, NUM_FLAGS);
54 
55 static struct {
56 	uint8_t private_key_be[BT_PRIV_KEY_LEN];
57 
58 	union {
59 		uint8_t public_key_be[BT_PUB_KEY_LEN];
60 		uint8_t dhkey_be[BT_DH_KEY_LEN];
61 	};
62 } ecc;
63 
64 /* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
65 static const uint8_t debug_private_key_be[BT_PRIV_KEY_LEN] = {
66 	0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38,
67 	0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
68 	0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99,
69 	0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd,
70 };
71 
72 static const uint8_t debug_public_key[BT_PUB_KEY_LEN] = {
73 	/* X */
74 	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
75 	0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
76 	0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
77 	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
78 	/* Y */
79 	0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
80 	0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
81 	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
82 	0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
83 };
84 
bt_pub_key_is_debug(uint8_t * cmp_pub_key)85 bool bt_pub_key_is_debug(uint8_t *cmp_pub_key)
86 {
87 	return memcmp(cmp_pub_key, debug_public_key, BT_PUB_KEY_LEN) == 0;
88 }
89 
bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN])90 bool bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN])
91 {
92 	uint8_t key_be[BT_PUB_KEY_LEN + 1];
93 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
94 	psa_status_t ret;
95 	psa_key_id_t handle;
96 
97 	psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
98 	psa_set_key_bits(&attr, 256);
99 	psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
100 	psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
101 
102 	/* PSA expects secp256r1 public key to start with a predefined 0x04 byte */
103 	key_be[0] = 0x04;
104 	sys_memcpy_swap(&key_be[1], key, BT_PUB_KEY_COORD_LEN);
105 	sys_memcpy_swap(&key_be[1 + BT_PUB_KEY_COORD_LEN], &key[BT_PUB_KEY_COORD_LEN],
106 			BT_PUB_KEY_COORD_LEN);
107 
108 	ret = psa_import_key(&attr, key_be, sizeof(key_be), &handle);
109 	psa_reset_key_attributes(&attr);
110 
111 	if (ret == PSA_SUCCESS) {
112 		psa_destroy_key(handle);
113 		return true;
114 	}
115 
116 	LOG_ERR("psa_import_key() returned status %d", ret);
117 	return false;
118 }
119 
set_key_attributes(psa_key_attributes_t * attr)120 static void set_key_attributes(psa_key_attributes_t *attr)
121 {
122 	psa_set_key_type(attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
123 	psa_set_key_bits(attr, 256);
124 	psa_set_key_usage_flags(attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE);
125 	psa_set_key_algorithm(attr, PSA_ALG_ECDH);
126 }
127 
generate_pub_key(struct k_work * work)128 static void generate_pub_key(struct k_work *work)
129 {
130 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
131 	struct bt_pub_key_cb *cb;
132 	psa_key_id_t key_id;
133 	uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1];
134 	size_t tmp_len;
135 	int err;
136 	psa_status_t ret;
137 
138 	set_key_attributes(&attr);
139 
140 	ret = psa_generate_key(&attr, &key_id);
141 	if (ret != PSA_SUCCESS) {
142 		LOG_ERR("Failed to generate ECC key %d", ret);
143 		err = BT_HCI_ERR_UNSPECIFIED;
144 		goto done;
145 	}
146 
147 	ret = psa_export_public_key(key_id, tmp_pub_key_buf, sizeof(tmp_pub_key_buf), &tmp_len);
148 	if (ret != PSA_SUCCESS) {
149 		LOG_ERR("Failed to export ECC public key %d", ret);
150 		err = BT_HCI_ERR_UNSPECIFIED;
151 		goto done;
152 	}
153 	/* secp256r1 PSA exported public key has an extra 0x04 predefined byte at
154 	 * the beginning of the buffer which is not part of the coordinate so
155 	 * we remove that.
156 	 */
157 	memcpy(ecc.public_key_be, &tmp_pub_key_buf[1], BT_PUB_KEY_LEN);
158 
159 	ret = psa_export_key(key_id, ecc.private_key_be, BT_PRIV_KEY_LEN, &tmp_len);
160 	if (ret != PSA_SUCCESS) {
161 		LOG_ERR("Failed to export ECC private key %d", ret);
162 		err = BT_HCI_ERR_UNSPECIFIED;
163 		goto done;
164 	}
165 
166 	ret = psa_destroy_key(key_id);
167 	if (ret != PSA_SUCCESS) {
168 		LOG_ERR("Failed to destroy ECC key ID %d", ret);
169 		err = BT_HCI_ERR_UNSPECIFIED;
170 		goto done;
171 	}
172 
173 	sys_memcpy_swap(pub_key, ecc.public_key_be, BT_PUB_KEY_COORD_LEN);
174 	sys_memcpy_swap(&pub_key[BT_PUB_KEY_COORD_LEN],
175 			&ecc.public_key_be[BT_PUB_KEY_COORD_LEN], BT_PUB_KEY_COORD_LEN);
176 
177 	atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
178 	err = 0;
179 
180 done:
181 	atomic_clear_bit(flags, PENDING_PUB_KEY);
182 
183 	/* Change to cooperative priority while we do the callbacks */
184 	k_sched_lock();
185 
186 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
187 		if (cb->func) {
188 			cb->func(err ? NULL : pub_key);
189 		}
190 	}
191 
192 	sys_slist_init(&pub_key_cb_slist);
193 
194 	k_sched_unlock();
195 }
196 
generate_dh_key(struct k_work * work)197 static void generate_dh_key(struct k_work *work)
198 {
199 	int err;
200 
201 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
202 	psa_key_id_t key_id;
203 	psa_status_t ret;
204 	/* PSA expects secp256r1 public key to start with a predefined 0x04 byte
205 	 * at the beginning the buffer.
206 	 */
207 	uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1] = { 0x04 };
208 	size_t tmp_len;
209 
210 	set_key_attributes(&attr);
211 
212 	const uint8_t *priv_key = (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) ?
213 				   debug_private_key_be :
214 				   ecc.private_key_be);
215 	ret = psa_import_key(&attr, priv_key, BT_PRIV_KEY_LEN, &key_id);
216 	if (ret != PSA_SUCCESS) {
217 		err = -EIO;
218 		LOG_ERR("Failed to import the private key for key agreement %d", ret);
219 		goto exit;
220 	}
221 
222 	memcpy(&tmp_pub_key_buf[1], ecc.public_key_be, BT_PUB_KEY_LEN);
223 	ret = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, tmp_pub_key_buf, sizeof(tmp_pub_key_buf),
224 				    ecc.dhkey_be, BT_DH_KEY_LEN, &tmp_len);
225 	if (ret != PSA_SUCCESS) {
226 		err = -EIO;
227 		LOG_ERR("Raw key agreement failed %d", ret);
228 		goto exit;
229 	}
230 
231 	ret = psa_destroy_key(key_id);
232 	if (ret != PSA_SUCCESS) {
233 		LOG_ERR("Failed to destroy the key %d", ret);
234 		err = -EIO;
235 		goto exit;
236 	}
237 
238 	err = 0;
239 
240 exit:
241 	/* Change to cooperative priority while we do the callback */
242 	k_sched_lock();
243 
244 	if (dh_key_cb) {
245 		bt_dh_key_cb_t cb = dh_key_cb;
246 
247 		dh_key_cb = NULL;
248 		atomic_clear_bit(flags, PENDING_DHKEY);
249 
250 		if (err) {
251 			cb(NULL);
252 		} else {
253 			uint8_t dhkey[BT_DH_KEY_LEN];
254 
255 			sys_memcpy_swap(dhkey, ecc.dhkey_be, sizeof(ecc.dhkey_be));
256 			cb(dhkey);
257 		}
258 	}
259 
260 	k_sched_unlock();
261 }
262 
bt_pub_key_gen(struct bt_pub_key_cb * new_cb)263 int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
264 {
265 	struct bt_pub_key_cb *cb;
266 
267 	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
268 		atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
269 		__ASSERT_NO_MSG(new_cb->func != NULL);
270 		new_cb->func(debug_public_key);
271 		return 0;
272 	}
273 
274 	if (!new_cb) {
275 		return -EINVAL;
276 	}
277 
278 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
279 		if (cb == new_cb) {
280 			LOG_DBG("Callback already registered");
281 			return -EALREADY;
282 		}
283 	}
284 
285 	if (atomic_test_bit(flags, PENDING_DHKEY)) {
286 		LOG_WRN("Busy performing another ECDH operation");
287 		return -EBUSY;
288 	}
289 
290 	sys_slist_prepend(&pub_key_cb_slist, &new_cb->node);
291 
292 	if (atomic_test_and_set_bit(flags, PENDING_PUB_KEY)) {
293 		return 0;
294 	}
295 
296 	atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
297 
298 	if (IS_ENABLED(CONFIG_BT_LONG_WQ)) {
299 		bt_long_wq_submit(&pub_key_work);
300 	} else {
301 		k_work_submit(&pub_key_work);
302 	}
303 
304 	return 0;
305 }
306 
bt_pub_key_hci_disrupted(void)307 void bt_pub_key_hci_disrupted(void)
308 {
309 	struct bt_pub_key_cb *cb;
310 
311 	atomic_clear_bit(flags, PENDING_PUB_KEY);
312 
313 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
314 		if (cb->func) {
315 			cb->func(NULL);
316 		}
317 	}
318 
319 	sys_slist_init(&pub_key_cb_slist);
320 }
321 
bt_pub_key_get(void)322 const uint8_t *bt_pub_key_get(void)
323 {
324 	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
325 		return debug_public_key;
326 	}
327 
328 	if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
329 		return pub_key;
330 	}
331 
332 	return NULL;
333 }
334 
bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN],bt_dh_key_cb_t cb)335 int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb)
336 {
337 	if (dh_key_cb == cb) {
338 		return -EALREADY;
339 	}
340 
341 	if (!atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
342 		return -EADDRNOTAVAIL;
343 	}
344 
345 	if (dh_key_cb ||
346 	    atomic_test_bit(flags, PENDING_PUB_KEY) ||
347 	    atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
348 		return -EBUSY;
349 	}
350 
351 	dh_key_cb = cb;
352 
353 	/* Convert X and Y coordinates from little-endian to
354 	 * big-endian (expected by the crypto API).
355 	 */
356 	sys_memcpy_swap(ecc.public_key_be, remote_pk, BT_PUB_KEY_COORD_LEN);
357 	sys_memcpy_swap(&ecc.public_key_be[BT_PUB_KEY_COORD_LEN],
358 			&remote_pk[BT_PUB_KEY_COORD_LEN], BT_PUB_KEY_COORD_LEN);
359 
360 	if (IS_ENABLED(CONFIG_BT_LONG_WQ)) {
361 		bt_long_wq_submit(&dh_key_work);
362 	} else {
363 		k_work_submit(&dh_key_work);
364 	}
365 
366 	return 0;
367 }
368 
369 #ifdef ZTEST_UNITTEST
bt_ecc_get_public_key(void)370 uint8_t const *bt_ecc_get_public_key(void)
371 {
372 	return pub_key;
373 }
374 
bt_ecc_get_internal_debug_public_key(void)375 uint8_t const *bt_ecc_get_internal_debug_public_key(void)
376 {
377 	return debug_public_key;
378 }
379 
bt_ecc_get_pub_key_cb_slist(void)380 sys_slist_t *bt_ecc_get_pub_key_cb_slist(void)
381 {
382 	return &pub_key_cb_slist;
383 }
384 
bt_ecc_get_dh_key_cb(void)385 bt_dh_key_cb_t *bt_ecc_get_dh_key_cb(void)
386 {
387 	return &dh_key_cb;
388 }
389 #endif /* ZTEST_UNITTEST */
390