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