blob: d72280e545b7269af4e5b80d8c8b0cef99004fc5 [file] [log] [blame]
Szymon Janc684ffd12016-05-24 17:15:03 +02001/**
2 * @file hci_ecc.c
3 * HCI ECC emulation
4 */
5
6/*
7 * Copyright (c) 2016 Intel Corporation
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22#include <zephyr.h>
23#include <atomic.h>
24#include <microkernel/task.h>
25#include <misc/byteorder.h>
Szymon Janca0a52692016-07-19 11:55:21 +020026#include <misc/nano_work.h>
Flavio Santese6ffc0e2016-07-24 23:52:50 -050027#include <tinycrypt/constants.h>
Szymon Janc684ffd12016-05-24 17:15:03 +020028#include <tinycrypt/utils.h>
29#include <tinycrypt/ecc.h>
30#include <tinycrypt/ecc_dh.h>
Johan Hedbergfbb2fe82016-06-27 09:15:56 +030031#include <bluetooth/bluetooth.h>
Szymon Janc684ffd12016-05-24 17:15:03 +020032#include <bluetooth/log.h>
33#include <bluetooth/hci.h>
34#include <bluetooth/driver.h>
35#include "hci_core.h"
36
37#if !defined(CONFIG_BLUETOOTH_DEBUG_HCI_CORE)
38#undef BT_DBG
39#define BT_DBG(fmt, ...)
40#endif
41
42/* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
43static const uint32_t debug_private_key[8] = {
44 0xcd3c1abd, 0x5899b8a6, 0xeb40b799, 0x4aff607b, 0xd2103f50, 0x74c9b3e3,
45 0xa3c55f38, 0x3f49f6d4
46};
47
48static struct nano_fifo ecc_queue;
49static int (*drv_send)(struct net_buf *buf);
50static uint32_t private_key[8];
51
52static void send_cmd_status(uint16_t opcode, uint8_t status)
53{
54 struct bt_hci_evt_cmd_status *evt;
55 struct bt_hci_evt_hdr *hdr;
56 struct net_buf *buf;
57
58 BT_DBG("opcode %x status %x", opcode, status);
59
Szymon Janc9c68fd42016-06-28 16:48:01 +020060 buf = bt_buf_get_evt(BT_HCI_EVT_CMD_STATUS);
Szymon Janc684ffd12016-05-24 17:15:03 +020061 if (!buf) {
62 BT_ERR("No available event buffers!");
63 return;
64 }
65
66 hdr = net_buf_add(buf, sizeof(*hdr));
67 hdr->evt = BT_HCI_EVT_CMD_STATUS;
68 hdr->len = sizeof(*evt);
69
70 evt = net_buf_add(buf, sizeof(*evt));
71 evt->ncmd = 1;
72 evt->opcode = sys_cpu_to_le16(opcode);
73 evt->status = status;
74
75 bt_recv(buf);
76}
77
78static void emulate_le_p256_public_key_cmd(struct net_buf *buf)
79{
80 struct bt_hci_evt_le_p256_public_key_complete *evt;
81 struct bt_hci_evt_le_meta_event *meta;
82 struct bt_hci_evt_hdr *hdr;
83 EccPoint pkey;
Flavio Santese6ffc0e2016-07-24 23:52:50 -050084 int rc;
Szymon Janc684ffd12016-05-24 17:15:03 +020085
86 BT_DBG();
87
88 net_buf_unref(buf);
89
90 send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, 0);
91
Szymon Janc9c68fd42016-06-28 16:48:01 +020092 buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT);
Szymon Janc684ffd12016-05-24 17:15:03 +020093 if (!buf) {
94 BT_ERR("No available event buffers!");
95 return;
96 }
97
98 hdr = net_buf_add(buf, sizeof(*hdr));
99 hdr->evt = BT_HCI_EVT_LE_META_EVENT;
100 hdr->len = sizeof(*meta) + sizeof(*evt);
101
102 meta = net_buf_add(buf, sizeof(*meta));
103 meta->subevent = BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE;
104
105 evt = net_buf_add(buf, sizeof(*evt));
106 evt->status = 0;
107
108 do {
109 uint32_t random[8];
110
111 if (bt_rand((uint8_t *)random, sizeof(random))) {
112 BT_ERR("Failed to get random bytes for ECC keys");
113 evt->status = 0x1f; /* unspecified error */
114 break;
115 }
116
Flavio Santese6ffc0e2016-07-24 23:52:50 -0500117 rc = ecc_make_key(&pkey, private_key, random);
118 if (rc == TC_CRYPTO_FAIL) {
Szymon Janc684ffd12016-05-24 17:15:03 +0200119 BT_ERR("Failed to create ECC public/private pair");
120 evt->status = 0x1f; /* unspecified error */
121 break;
122 }
123
124 /* make sure generated key isn't debug key */
125 } while (memcmp(private_key, debug_private_key, 32) == 0);
126
127 if (!evt->status) {
128 memcpy(evt->key, pkey.x, 32);
129 memcpy(&evt->key[32], pkey.y, 32);
130 } else {
131 memset(evt->key, 0, sizeof(evt->key));
132 }
133
134 bt_recv(buf);
135}
136
137static void emulate_le_generate_dhkey(struct net_buf *buf)
138{
139 struct bt_hci_evt_le_generate_dhkey_complete *evt;
140 struct bt_hci_cp_le_generate_dhkey *cmd;
141 struct bt_hci_evt_le_meta_event *meta;
142 struct bt_hci_evt_hdr *hdr;
143 EccPoint pk;
144
145 cmd = (void *)buf->data + sizeof(struct bt_hci_cmd_hdr);
146
147 /* TODO verify cmd parameters? */
148 send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, 0);
149
150 memcpy(pk.x, cmd->key, 32);
151 memcpy(pk.y, &cmd->key[32], 32);
152
153 net_buf_unref(buf);
154
Szymon Janc9c68fd42016-06-28 16:48:01 +0200155 buf = bt_buf_get_evt(BT_HCI_EVT_LE_META_EVENT);
Szymon Janc684ffd12016-05-24 17:15:03 +0200156 if (!buf) {
157 BT_ERR("No available event buffers!");
158 return;
159 }
160
161 hdr = net_buf_add(buf, sizeof(*hdr));
162 hdr->evt = BT_HCI_EVT_LE_META_EVENT;
163 hdr->len = sizeof(*meta) + sizeof(*evt);
164
165 meta = net_buf_add(buf, sizeof(*meta));
166 meta->subevent = BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE;
167
168 evt = net_buf_add(buf, sizeof(*evt));
169 evt->status = 0;
170
171 if (ecc_valid_public_key(&pk) < 0) {
172 evt->status = 0x1f; /* unspecified error */
173 memset(evt->dhkey, 0, sizeof(evt->dhkey));
Szymon Jancd7ae97d2016-05-25 18:00:14 +0200174 bt_recv(buf);
Szymon Janc684ffd12016-05-24 17:15:03 +0200175 return;
176 }
177
178 if (ecdh_shared_secret((uint32_t *)evt->dhkey, &pk, private_key)
Flavio Santese6ffc0e2016-07-24 23:52:50 -0500179 == TC_CRYPTO_FAIL) {
Szymon Janc684ffd12016-05-24 17:15:03 +0200180 evt->status = 0x1f; /* unspecified error */
181 memset(evt->dhkey, 0, sizeof(evt->dhkey));
182 }
183
184 bt_recv(buf);
185}
186
187static void ecc_task(void)
188{
189 nano_fifo_init(&ecc_queue);
190
191 while (true) {
192 struct net_buf *buf;
193
194 buf = nano_task_fifo_get(&ecc_queue, TICKS_UNLIMITED);
195
196 switch (bt_hci_get_cmd_opcode(buf)) {
197 case BT_HCI_OP_LE_P256_PUBLIC_KEY:
198 emulate_le_p256_public_key_cmd(buf);
199 break;
200 case BT_HCI_OP_LE_GENERATE_DHKEY:
201 emulate_le_generate_dhkey(buf);
202 break;
203 default:
204 BT_ERR("Unhandled command for ECC task (opcode %x)",
205 bt_hci_get_cmd_opcode(buf));
206 net_buf_unref(buf);
207 break;
208 }
209 }
210}
211
212/* TODO measure required stack size, 1024 is not enough */
213DEFINE_TASK(ECC_TASKID, 10, ecc_task, 2048, EXE);
214
215static void clear_ecc_events(struct net_buf *buf)
216{
217 struct bt_hci_cp_le_set_event_mask *cmd;
218
219 cmd = (void *)buf->data + sizeof(struct bt_hci_cmd_hdr);
220
221 /*
222 * don't enable controller ECC events as those will be generated from
223 * emulation code
224 */
225 cmd->events[0] &= ~0x80; /* LE Read Local P-256 PKey Compl */
226 cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */
227}
228
229static int ecc_send(struct net_buf *buf)
230{
231 if (bt_buf_get_type(buf) == BT_BUF_CMD) {
232 switch (bt_hci_get_cmd_opcode(buf)) {
233 case BT_HCI_OP_LE_P256_PUBLIC_KEY:
234 case BT_HCI_OP_LE_GENERATE_DHKEY:
Johan Hedberg4c954642016-06-05 17:36:46 +0300235 net_buf_put(&ecc_queue, buf);
Szymon Janc684ffd12016-05-24 17:15:03 +0200236 return 0;
237 case BT_HCI_OP_LE_SET_EVENT_MASK:
238 clear_ecc_events(buf);
239 break;
240 default:
241 break;
242 }
243 }
244
245 return drv_send(buf);
246}
247
248void bt_hci_ecc_init(void)
249{
250 /* set wrapper for driver send function */
251 drv_send = bt_dev.drv->send;
252 bt_dev.drv->send = ecc_send;
253}