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