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