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 <stdint.h>
9 
10 #include <zephyr/sys/byteorder.h>
11 #include <zephyr/sys/check.h>
12 #include <zephyr/bluetooth/hci.h>
13 
14 #include <psa/crypto.h>
15 
16 #include "ecc.h"
17 #include "hci_core.h"
18 
19 #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(bt_ecc);
22 
23 static uint8_t pub_key[BT_PUB_KEY_LEN];
24 static sys_slist_t pub_key_cb_slist;
25 static bt_dh_key_cb_t dh_key_cb;
26 
27 static const uint8_t debug_public_key[BT_PUB_KEY_LEN] = {
28 	/* X */
29 	0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
30 	0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
31 	0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
32 	0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
33 	/* Y */
34 	0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
35 	0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
36 	0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
37 	0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
38 };
39 
bt_pub_key_is_debug(uint8_t * cmp_pub_key)40 bool bt_pub_key_is_debug(uint8_t *cmp_pub_key)
41 {
42 	return memcmp(cmp_pub_key, debug_public_key, BT_PUB_KEY_LEN) == 0;
43 }
44 
bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN])45 bool bt_pub_key_is_valid(const uint8_t key[BT_PUB_KEY_LEN])
46 {
47 	uint8_t key_be[BT_PUB_KEY_LEN + 1];
48 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
49 	psa_status_t ret;
50 	psa_key_id_t handle;
51 
52 	psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
53 	psa_set_key_bits(&attr, 256);
54 	psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
55 	psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
56 
57 	/* PSA expects secp256r1 public key to start with a predefined 0x04 byte */
58 	key_be[0] = 0x04;
59 	sys_memcpy_swap(&key_be[1], key, BT_PUB_KEY_COORD_LEN);
60 	sys_memcpy_swap(&key_be[1 + BT_PUB_KEY_COORD_LEN], &key[BT_PUB_KEY_COORD_LEN],
61 			BT_PUB_KEY_COORD_LEN);
62 
63 	ret = psa_import_key(&attr, key_be, sizeof(key_be), &handle);
64 	psa_reset_key_attributes(&attr);
65 
66 	if (ret == PSA_SUCCESS) {
67 		psa_destroy_key(handle);
68 		return true;
69 	}
70 
71 	return false;
72 }
73 
bt_pub_key_gen(struct bt_pub_key_cb * new_cb)74 int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
75 {
76 	struct bt_pub_key_cb *cb;
77 	int err;
78 
79 	/*
80 	 * We check for both "LE Read Local P-256 Public Key" and
81 	 * "LE Generate DH Key" support here since both commands are needed for
82 	 * ECC support. If "LE Generate DH Key" is not supported then there
83 	 * is no point in reading local public key.
84 	 */
85 	if (!BT_CMD_TEST(bt_dev.supported_commands, 34, 1) ||
86 	    !BT_CMD_TEST(bt_dev.supported_commands, 34, 2)) {
87 		LOG_WRN("ECC HCI commands not available");
88 		return -ENOTSUP;
89 	}
90 
91 	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
92 		if (!BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
93 			LOG_WRN("ECC Debug keys HCI command not available");
94 		} else {
95 			atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
96 			__ASSERT_NO_MSG(new_cb->func != NULL);
97 			new_cb->func(debug_public_key);
98 			return 0;
99 		}
100 	}
101 
102 	if (!new_cb) {
103 		return -EINVAL;
104 	}
105 
106 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
107 		if (cb == new_cb) {
108 			LOG_WRN("Callback already registered");
109 			return -EALREADY;
110 		}
111 	}
112 
113 	sys_slist_prepend(&pub_key_cb_slist, &new_cb->node);
114 
115 	if (atomic_test_and_set_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
116 		return 0;
117 	}
118 
119 	atomic_clear_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
120 
121 	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_P256_PUBLIC_KEY, NULL, NULL);
122 	if (err) {
123 
124 		LOG_ERR("Sending LE P256 Public Key command failed");
125 		atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
126 
127 		SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
128 			if (cb->func) {
129 				cb->func(NULL);
130 			}
131 		}
132 
133 		sys_slist_init(&pub_key_cb_slist);
134 		return err;
135 	}
136 
137 	return 0;
138 }
139 
bt_pub_key_hci_disrupted(void)140 void bt_pub_key_hci_disrupted(void)
141 {
142 	struct bt_pub_key_cb *cb;
143 
144 	atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
145 
146 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
147 		if (cb->func) {
148 			cb->func(NULL);
149 		}
150 	}
151 
152 	sys_slist_init(&pub_key_cb_slist);
153 }
154 
bt_pub_key_get(void)155 const uint8_t *bt_pub_key_get(void)
156 {
157 	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
158 	    BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
159 		return debug_public_key;
160 	}
161 
162 	if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
163 		return pub_key;
164 	}
165 
166 	return NULL;
167 }
168 
hci_generate_dhkey_v1(const uint8_t * remote_pk)169 static int hci_generate_dhkey_v1(const uint8_t *remote_pk)
170 {
171 	struct bt_hci_cp_le_generate_dhkey *cp;
172 	struct net_buf *buf;
173 
174 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
175 	if (!buf) {
176 		return -ENOBUFS;
177 	}
178 
179 	cp = net_buf_add(buf, sizeof(*cp));
180 	memcpy(cp->key, remote_pk, sizeof(cp->key));
181 
182 	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
183 }
184 
hci_generate_dhkey_v2(const uint8_t * remote_pk,uint8_t key_type)185 static int hci_generate_dhkey_v2(const uint8_t *remote_pk, uint8_t key_type)
186 {
187 	struct bt_hci_cp_le_generate_dhkey_v2 *cp;
188 	struct net_buf *buf;
189 
190 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY_V2, sizeof(*cp));
191 	if (!buf) {
192 		return -ENOBUFS;
193 	}
194 
195 	cp = net_buf_add(buf, sizeof(*cp));
196 	memcpy(cp->key, remote_pk, sizeof(cp->key));
197 	cp->key_type = key_type;
198 
199 	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY_V2, buf, NULL);
200 }
201 
bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN],bt_dh_key_cb_t cb)202 int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb)
203 {
204 	int err;
205 
206 	if (dh_key_cb == cb) {
207 		return -EALREADY;
208 	}
209 
210 	if (dh_key_cb || atomic_test_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY)) {
211 		return -EBUSY;
212 	}
213 
214 	if (!atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
215 		return -EADDRNOTAVAIL;
216 	}
217 
218 	dh_key_cb = cb;
219 
220 	if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
221 	    BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
222 		err = hci_generate_dhkey_v2(remote_pk,
223 					    BT_HCI_LE_KEY_TYPE_DEBUG);
224 	} else {
225 		err = hci_generate_dhkey_v1(remote_pk);
226 	}
227 
228 	if (err) {
229 		dh_key_cb = NULL;
230 		LOG_WRN("Failed to generate DHKey (err %d)", err);
231 		return err;
232 	}
233 
234 	return 0;
235 }
236 
bt_hci_evt_le_pkey_complete(struct net_buf * buf)237 void bt_hci_evt_le_pkey_complete(struct net_buf *buf)
238 {
239 	struct bt_hci_evt_le_p256_public_key_complete *evt = (void *)buf->data;
240 	struct bt_pub_key_cb *cb;
241 
242 	LOG_DBG("status: 0x%02x %s", evt->status, bt_hci_err_to_str(evt->status));
243 
244 	atomic_clear_bit(bt_dev.flags, BT_DEV_PUB_KEY_BUSY);
245 
246 	if (!evt->status) {
247 		memcpy(pub_key, evt->key, BT_PUB_KEY_LEN);
248 		atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
249 	}
250 
251 	SYS_SLIST_FOR_EACH_CONTAINER(&pub_key_cb_slist, cb, node) {
252 		if (cb->func) {
253 			cb->func(evt->status ? NULL : pub_key);
254 		}
255 	}
256 
257 	sys_slist_init(&pub_key_cb_slist);
258 }
259 
bt_hci_evt_le_dhkey_complete(struct net_buf * buf)260 void bt_hci_evt_le_dhkey_complete(struct net_buf *buf)
261 {
262 	struct bt_hci_evt_le_generate_dhkey_complete *evt = (void *)buf->data;
263 
264 	LOG_DBG("status: 0x%02x %s", evt->status, bt_hci_err_to_str(evt->status));
265 
266 	if (dh_key_cb) {
267 		bt_dh_key_cb_t cb = dh_key_cb;
268 
269 		dh_key_cb = NULL;
270 		cb(evt->status ? NULL : evt->dhkey);
271 	}
272 }
273 
274 #ifdef ZTEST_UNITTEST
bt_ecc_get_public_key(void)275 uint8_t const *bt_ecc_get_public_key(void)
276 {
277 	return pub_key;
278 }
279 
bt_ecc_get_internal_debug_public_key(void)280 uint8_t const *bt_ecc_get_internal_debug_public_key(void)
281 {
282 	return debug_public_key;
283 }
284 
bt_ecc_get_pub_key_cb_slist(void)285 sys_slist_t *bt_ecc_get_pub_key_cb_slist(void)
286 {
287 	return &pub_key_cb_slist;
288 }
289 
bt_ecc_get_dh_key_cb(void)290 bt_dh_key_cb_t *bt_ecc_get_dh_key_cb(void)
291 {
292 	return &dh_key_cb;
293 }
294 #endif /* ZTEST_UNITTEST */
295