1 /**
2  * @file hci_ecc.c
3  * HCI ECC emulation
4  */
5 
6 /*
7  * Copyright (c) 2016 Intel Corporation
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/atomic.h>
14 #include <zephyr/debug/stack.h>
15 #include <zephyr/sys/byteorder.h>
16 
17 #include <psa/crypto.h>
18 
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/buf.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/hci.h>
23 #include <zephyr/drivers/bluetooth.h>
24 
25 #include "common/bt_str.h"
26 
27 #include "hci_ecc.h"
28 #include "ecc.h"
29 
30 #ifdef CONFIG_BT_HCI_RAW
31 #include <zephyr/bluetooth/hci_raw.h>
32 #include "hci_raw_internal.h"
33 #else
34 #include "hci_core.h"
35 #endif
36 #include "long_wq.h"
37 
38 #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
39 #include <zephyr/logging/log.h>
40 LOG_MODULE_REGISTER(bt_hci_ecc);
41 
42 static void ecc_process(struct k_work *work);
43 K_WORK_DEFINE(ecc_work, ecc_process);
44 
45 /* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
46 static const uint8_t debug_private_key_be[BT_PRIV_KEY_LEN] = {
47 	0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38,
48 	0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
49 	0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99,
50 	0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd,
51 };
52 
53 enum {
54 	PENDING_PUB_KEY,
55 	PENDING_DHKEY,
56 
57 	USE_DEBUG_KEY,
58 
59 	/* Total number of flags - must be at the end of the enum */
60 	NUM_FLAGS,
61 };
62 
63 static ATOMIC_DEFINE(flags, NUM_FLAGS);
64 
65 static struct {
66 	uint8_t private_key_be[BT_PRIV_KEY_LEN];
67 
68 	union {
69 		uint8_t public_key_be[BT_PUB_KEY_LEN];
70 		uint8_t dhkey_be[BT_DH_KEY_LEN];
71 	};
72 } ecc;
73 
send_cmd_status(uint16_t opcode,uint8_t status)74 static void send_cmd_status(uint16_t opcode, uint8_t status)
75 {
76 	struct bt_hci_evt_cmd_status *evt;
77 	struct bt_hci_evt_hdr *hdr;
78 	struct net_buf *buf;
79 
80 	LOG_DBG("opcode %x status 0x%02x %s", opcode, status, bt_hci_err_to_str(status));
81 
82 	buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS, false, K_FOREVER);
83 	bt_buf_set_type(buf, BT_BUF_EVT);
84 
85 	hdr = net_buf_add(buf, sizeof(*hdr));
86 	hdr->evt = BT_HCI_EVT_CMD_STATUS;
87 	hdr->len = sizeof(*evt);
88 
89 	evt = net_buf_add(buf, sizeof(*evt));
90 	evt->ncmd = 1U;
91 	evt->opcode = sys_cpu_to_le16(opcode);
92 	evt->status = status;
93 
94 	bt_hci_recv(bt_dev.hci, buf);
95 }
96 
set_key_attributes(psa_key_attributes_t * attr)97 static void set_key_attributes(psa_key_attributes_t *attr)
98 {
99 	psa_set_key_type(attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
100 	psa_set_key_bits(attr, 256);
101 	psa_set_key_usage_flags(attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE);
102 	psa_set_key_algorithm(attr, PSA_ALG_ECDH);
103 }
104 
generate_keys(void)105 static uint8_t generate_keys(void)
106 {
107 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
108 	psa_key_id_t key_id;
109 	uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1];
110 	size_t tmp_len;
111 
112 	set_key_attributes(&attr);
113 
114 	if (psa_generate_key(&attr, &key_id) != PSA_SUCCESS) {
115 		LOG_ERR("Failed to generate ECC key");
116 		return BT_HCI_ERR_UNSPECIFIED;
117 	}
118 
119 	if (psa_export_public_key(key_id, tmp_pub_key_buf, sizeof(tmp_pub_key_buf),
120 				&tmp_len) != PSA_SUCCESS) {
121 		LOG_ERR("Failed to export ECC public key");
122 		return BT_HCI_ERR_UNSPECIFIED;
123 	}
124 	/* secp256r1 PSA exported public key has an extra 0x04 predefined byte at
125 	 * the beginning of the buffer which is not part of the coordinate so
126 	 * we remove that.
127 	 */
128 	memcpy(ecc.public_key_be, &tmp_pub_key_buf[1], BT_PUB_KEY_LEN);
129 
130 	if (psa_export_key(key_id, ecc.private_key_be, BT_PRIV_KEY_LEN,
131 			&tmp_len) != PSA_SUCCESS) {
132 		LOG_ERR("Failed to export ECC private key");
133 		return BT_HCI_ERR_UNSPECIFIED;
134 	}
135 
136 	if (psa_destroy_key(key_id) != PSA_SUCCESS) {
137 		LOG_ERR("Failed to destroy ECC key ID");
138 		return BT_HCI_ERR_UNSPECIFIED;
139 	}
140 
141 	return 0;
142 }
143 
emulate_le_p256_public_key_cmd(void)144 static void emulate_le_p256_public_key_cmd(void)
145 {
146 	struct bt_hci_evt_le_p256_public_key_complete *evt;
147 	struct bt_hci_evt_le_meta_event *meta;
148 	struct bt_hci_evt_hdr *hdr;
149 	struct net_buf *buf;
150 	uint8_t status;
151 
152 	LOG_DBG("");
153 
154 	status = generate_keys();
155 
156 	buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
157 
158 	hdr = net_buf_add(buf, sizeof(*hdr));
159 	hdr->evt = BT_HCI_EVT_LE_META_EVENT;
160 	hdr->len = sizeof(*meta) + sizeof(*evt);
161 
162 	meta = net_buf_add(buf, sizeof(*meta));
163 	meta->subevent = BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE;
164 
165 	evt = net_buf_add(buf, sizeof(*evt));
166 	evt->status = status;
167 
168 	if (status) {
169 		(void)memset(evt->key, 0, sizeof(evt->key));
170 	} else {
171 		/* Convert X and Y coordinates from big-endian (provided
172 		 * by crypto API) to little endian HCI.
173 		 */
174 		sys_memcpy_swap(evt->key, ecc.public_key_be, BT_PUB_KEY_COORD_LEN);
175 		sys_memcpy_swap(&evt->key[BT_PUB_KEY_COORD_LEN],
176 				&ecc.public_key_be[BT_PUB_KEY_COORD_LEN], BT_PUB_KEY_COORD_LEN);
177 	}
178 
179 	atomic_clear_bit(flags, PENDING_PUB_KEY);
180 
181 	bt_hci_recv(bt_dev.hci, buf);
182 }
183 
emulate_le_generate_dhkey(void)184 static void emulate_le_generate_dhkey(void)
185 {
186 	struct bt_hci_evt_le_generate_dhkey_complete *evt;
187 	struct bt_hci_evt_le_meta_event *meta;
188 	struct bt_hci_evt_hdr *hdr;
189 	struct net_buf *buf;
190 	int ret = 0;
191 	bool use_debug = atomic_test_bit(flags, USE_DEBUG_KEY);
192 
193 	psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
194 	psa_key_id_t key_id;
195 	/* PSA expects secp256r1 public key to start with a predefined 0x04 byte
196 	 * at the beginning the buffer.
197 	 */
198 	uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1] = { 0x04 };
199 	size_t tmp_len;
200 
201 	set_key_attributes(&attr);
202 
203 	if (psa_import_key(&attr, use_debug ? debug_private_key_be : ecc.private_key_be,
204 				BT_PRIV_KEY_LEN, &key_id) != PSA_SUCCESS) {
205 		ret = -EIO;
206 		LOG_ERR("Failed to import the private key for key agreement");
207 		goto exit;
208 	}
209 
210 	memcpy(&tmp_pub_key_buf[1], ecc.public_key_be, BT_PUB_KEY_LEN);
211 	if (psa_raw_key_agreement(PSA_ALG_ECDH, key_id, tmp_pub_key_buf,
212 				sizeof(tmp_pub_key_buf), ecc.dhkey_be, BT_DH_KEY_LEN,
213 				&tmp_len) != PSA_SUCCESS) {
214 		ret = -EIO;
215 		LOG_ERR("Raw key agreement failed");
216 		goto exit;
217 	}
218 
219 	if (psa_destroy_key(key_id) != PSA_SUCCESS) {
220 		LOG_ERR("Failed to destroy the key");
221 		ret = -EIO;
222 	}
223 
224 exit:
225 	buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER);
226 
227 	hdr = net_buf_add(buf, sizeof(*hdr));
228 	hdr->evt = BT_HCI_EVT_LE_META_EVENT;
229 	hdr->len = sizeof(*meta) + sizeof(*evt);
230 
231 	meta = net_buf_add(buf, sizeof(*meta));
232 	meta->subevent = BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE;
233 
234 	evt = net_buf_add(buf, sizeof(*evt));
235 
236 	if (ret != 0) {
237 		evt->status = BT_HCI_ERR_UNSPECIFIED;
238 		(void)memset(evt->dhkey, 0xff, sizeof(evt->dhkey));
239 	} else {
240 		evt->status = 0U;
241 		/* Convert from big-endian (provided by crypto API) to
242 		 * little-endian HCI.
243 		 */
244 		sys_memcpy_swap(evt->dhkey, ecc.dhkey_be, sizeof(ecc.dhkey_be));
245 	}
246 
247 	atomic_clear_bit(flags, PENDING_DHKEY);
248 
249 	bt_hci_recv(bt_dev.hci, buf);
250 }
251 
ecc_process(struct k_work * work)252 static void ecc_process(struct k_work *work)
253 {
254 	if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
255 		emulate_le_p256_public_key_cmd();
256 	} else if (atomic_test_bit(flags, PENDING_DHKEY)) {
257 		emulate_le_generate_dhkey();
258 	} else {
259 		__ASSERT(0, "Unhandled ECC command");
260 	}
261 }
262 
clear_ecc_events(struct net_buf * buf)263 static void clear_ecc_events(struct net_buf *buf)
264 {
265 	struct bt_hci_cp_le_set_event_mask *cmd;
266 
267 	cmd = (void *)(buf->data + sizeof(struct bt_hci_cmd_hdr));
268 
269 	/*
270 	 * don't enable controller ECC events as those will be generated from
271 	 * emulation code
272 	 */
273 	cmd->events[0] &= ~0x80; /* LE Read Local P-256 PKey Compl */
274 	cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */
275 }
276 
le_gen_dhkey(uint8_t * key,uint8_t key_type)277 static uint8_t le_gen_dhkey(uint8_t *key, uint8_t key_type)
278 {
279 	if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
280 		return BT_HCI_ERR_CMD_DISALLOWED;
281 	}
282 
283 	if (key_type > BT_HCI_LE_KEY_TYPE_DEBUG) {
284 		return BT_HCI_ERR_INVALID_PARAM;
285 	}
286 
287 	if (atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
288 		return BT_HCI_ERR_CMD_DISALLOWED;
289 	}
290 
291 	/* Convert X and Y coordinates from little-endian HCI to
292 	 * big-endian (expected by the crypto API).
293 	 */
294 	sys_memcpy_swap(ecc.public_key_be, key, BT_PUB_KEY_COORD_LEN);
295 	sys_memcpy_swap(&ecc.public_key_be[BT_PUB_KEY_COORD_LEN], &key[BT_PUB_KEY_COORD_LEN],
296 			BT_PUB_KEY_COORD_LEN);
297 
298 	atomic_set_bit_to(flags, USE_DEBUG_KEY,
299 			  key_type == BT_HCI_LE_KEY_TYPE_DEBUG);
300 
301 	bt_long_wq_submit(&ecc_work);
302 
303 	return BT_HCI_ERR_SUCCESS;
304 }
305 
le_gen_dhkey_v1(struct net_buf * buf)306 static void le_gen_dhkey_v1(struct net_buf *buf)
307 {
308 	struct bt_hci_cp_le_generate_dhkey *cmd;
309 	uint8_t status;
310 
311 	cmd = (void *)buf->data;
312 	status = le_gen_dhkey(cmd->key, BT_HCI_LE_KEY_TYPE_GENERATED);
313 
314 	net_buf_unref(buf);
315 	send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, status);
316 }
317 
le_gen_dhkey_v2(struct net_buf * buf)318 static void le_gen_dhkey_v2(struct net_buf *buf)
319 {
320 	struct bt_hci_cp_le_generate_dhkey_v2 *cmd;
321 	uint8_t status;
322 
323 	cmd = (void *)buf->data;
324 	status = le_gen_dhkey(cmd->key, cmd->key_type);
325 
326 	net_buf_unref(buf);
327 	send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY_V2, status);
328 }
329 
le_p256_pub_key(struct net_buf * buf)330 static void le_p256_pub_key(struct net_buf *buf)
331 {
332 	uint8_t status;
333 
334 	net_buf_unref(buf);
335 
336 	if (atomic_test_bit(flags, PENDING_DHKEY)) {
337 		status = BT_HCI_ERR_CMD_DISALLOWED;
338 	} else if (atomic_test_and_set_bit(flags, PENDING_PUB_KEY)) {
339 		status = BT_HCI_ERR_CMD_DISALLOWED;
340 	} else {
341 		bt_long_wq_submit(&ecc_work);
342 		status = BT_HCI_ERR_SUCCESS;
343 	}
344 
345 	send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, status);
346 }
347 
bt_hci_ecc_send(struct net_buf * buf)348 int bt_hci_ecc_send(struct net_buf *buf)
349 {
350 	if (bt_buf_get_type(buf) == BT_BUF_CMD) {
351 		struct bt_hci_cmd_hdr *chdr = (void *)buf->data;
352 
353 		switch (sys_le16_to_cpu(chdr->opcode)) {
354 		case BT_HCI_OP_LE_P256_PUBLIC_KEY:
355 			net_buf_pull(buf, sizeof(*chdr));
356 			le_p256_pub_key(buf);
357 			return 0;
358 		case BT_HCI_OP_LE_GENERATE_DHKEY:
359 			net_buf_pull(buf, sizeof(*chdr));
360 			le_gen_dhkey_v1(buf);
361 			return 0;
362 		case BT_HCI_OP_LE_GENERATE_DHKEY_V2:
363 			net_buf_pull(buf, sizeof(*chdr));
364 			le_gen_dhkey_v2(buf);
365 			return 0;
366 		case BT_HCI_OP_LE_SET_EVENT_MASK:
367 			clear_ecc_events(buf);
368 			break;
369 		default:
370 			break;
371 		}
372 	}
373 
374 	return bt_hci_send(bt_dev.hci, buf);
375 }
376 
bt_hci_ecc_supported_commands(uint8_t * supported_commands)377 void bt_hci_ecc_supported_commands(uint8_t *supported_commands)
378 {
379 	/* LE Read Local P-256 Public Key */
380 	supported_commands[34] |= BIT(1);
381 	/* LE Generate DH Key v1 */
382 	supported_commands[34] |= BIT(2);
383 	/* LE Generate DH Key v2 */
384 	supported_commands[41] |= BIT(2);
385 }
386 
default_CSPRNG(uint8_t * dst,unsigned int len)387 int default_CSPRNG(uint8_t *dst, unsigned int len)
388 {
389 	return !bt_rand(dst, len);
390 }
391