| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2021, Jacques Gagnon | ||
| 3 | * SPDX-License-Identifier: Apache-2.0 | ||
| 4 | * | ||
| 5 | * Based on Zephyr's subsys/bluetooth/host/smp.c: | ||
| 6 | * Copyright (c) 2017 Nordic Semiconductor ASA | ||
| 7 | * Copyright (c) 2015-2016 Intel Corporation | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <stdio.h> | ||
| 11 | #include <esp_random.h> | ||
| 12 | #include "host.h" | ||
| 13 | #include "hci.h" | ||
| 14 | #include "att_hid.h" | ||
| 15 | #include "smp.h" | ||
| 16 | #include "zephyr/smp.h" | ||
| 17 | |||
| 18 | static void bt_smp_mrand_half(struct bt_dev *device, uint8_t *data, uint32_t len); | ||
| 19 | static void bt_smp_mrand_complete(struct bt_dev *device, uint8_t *data, uint32_t len); | ||
| 20 | static void bt_smp_confirm_half(struct bt_dev *device, uint8_t *data, uint32_t len); | ||
| 21 | static void bt_smp_confirm_complete(struct bt_dev *device, uint8_t *data, uint32_t len); | ||
| 22 | static void bt_smp_stk_complete(struct bt_dev *device, uint8_t *data, uint32_t len); | ||
| 23 | static void bt_smp_key_distribution(struct bt_dev *device); | ||
| 24 | static void bt_smp_pairing_req(uint16_t handle, struct bt_smp_pairing *pairing_req); | ||
| 25 | static void bt_smp_pairing_confirm(uint16_t handle, uint8_t val[16]); | ||
| 26 | static void bt_smp_encrypt_info(uint16_t handle, uint8_t ltk[16]); | ||
| 27 | static void bt_smp_master_ident(uint16_t handle, uint8_t ediv[2], uint8_t rand[8]); | ||
| 28 | static void bt_smp_ident_info(uint16_t handle, uint8_t irk[16]); | ||
| 29 | static void bt_smp_ident_addr_info(uint16_t handle, bt_addr_le_t *le_bdaddr); | ||
| 30 | static void bt_smp_signing_info(uint16_t handle, uint8_t csrk[16]); | ||
| 31 | |||
| 32 | ✗ | static void xor_128(const uint8_t p[16], const uint8_t q[16], uint8_t r[16]) { | |
| 33 | ✗ | size_t len = 16; | |
| 34 | |||
| 35 | ✗ | while (len--) { | |
| 36 | ✗ | *r++ = *p++ ^ *q++; | |
| 37 | } | ||
| 38 | ✗ | } | |
| 39 | |||
| 40 | ✗ | static int32_t smp_c1_part1(struct bt_dev *device, const uint8_t k[16], const uint8_t r[16], | |
| 41 | const uint8_t preq[7], const uint8_t pres[7], | ||
| 42 | const bt_addr_le_t *ia, const bt_addr_le_t *ra, | ||
| 43 | uint8_t enc_data[16]) { | ||
| 44 | ✗ | uint8_t p1[16]; | |
| 45 | |||
| 46 | /* pres, preq, rat and iat are concatenated to generate p1 */ | ||
| 47 | ✗ | p1[0] = ia->type; | |
| 48 | ✗ | p1[1] = ra->type; | |
| 49 | ✗ | memcpy(p1 + 2, preq, 7); | |
| 50 | ✗ | memcpy(p1 + 9, pres, 7); | |
| 51 | |||
| 52 | /* c1 = e(k, e(k, r XOR p1) XOR p2) */ | ||
| 53 | |||
| 54 | /* Using enc_data as temporary output buffer */ | ||
| 55 | ✗ | xor_128(r, p1, enc_data); | |
| 56 | |||
| 57 | ✗ | return bt_hci_get_encrypt(device, bt_smp_confirm_half, k, enc_data); | |
| 58 | } | ||
| 59 | |||
| 60 | ✗ | static int32_t smp_c1_part2(struct bt_dev *device, const uint8_t k[16], const uint8_t r[16], | |
| 61 | const uint8_t preq[7], const uint8_t pres[7], | ||
| 62 | const bt_addr_le_t *ia, const bt_addr_le_t *ra, | ||
| 63 | uint8_t enc_data[16]) { | ||
| 64 | ✗ | uint8_t p2[16]; | |
| 65 | |||
| 66 | /* ra is concatenated with ia and padding to generate p2 */ | ||
| 67 | ✗ | memcpy(p2, ra->a.val, 6); | |
| 68 | ✗ | memcpy(p2 + 6, ia->a.val, 6); | |
| 69 | ✗ | (void)memset(p2 + 12, 0, 4); | |
| 70 | |||
| 71 | ✗ | xor_128(enc_data, p2, enc_data); | |
| 72 | |||
| 73 | ✗ | return bt_hci_get_encrypt(device, bt_smp_confirm_complete, k, enc_data); | |
| 74 | } | ||
| 75 | |||
| 76 | ✗ | static int32_t smp_s1(struct bt_dev *device, const uint8_t k[16], const uint8_t r1[16], | |
| 77 | const uint8_t r2[16], uint8_t out[16]) | ||
| 78 | { | ||
| 79 | /* The most significant 64-bits of r1 are discarded to generate | ||
| 80 | * r1' and the most significant 64-bits of r2 are discarded to | ||
| 81 | * generate r2'. | ||
| 82 | * r1' is concatenated with r2' to generate r' which is used as | ||
| 83 | * the 128-bit input parameter plaintextData to security function e: | ||
| 84 | * | ||
| 85 | * r' = r1' || r2' | ||
| 86 | */ | ||
| 87 | ✗ | memcpy(out, r2, 8); | |
| 88 | ✗ | memcpy(out + 8, r1, 8); | |
| 89 | |||
| 90 | /* s1(k, r1 , r2) = e(k, r') */ | ||
| 91 | ✗ | return bt_hci_get_encrypt(device, bt_smp_stk_complete, k, out); | |
| 92 | } | ||
| 93 | |||
| 94 | ✗ | static void bt_smp_mrand_half(struct bt_dev *device, uint8_t *data, uint32_t len) { | |
| 95 | ✗ | memcpy(device->rand, data, len); | |
| 96 | ✗ | } | |
| 97 | |||
| 98 | ✗ | static void bt_smp_mrand_complete(struct bt_dev *device, uint8_t *data, uint32_t len) { | |
| 99 | ✗ | bt_addr_le_t le_local; | |
| 100 | ✗ | uint8_t tk[16] = {0}; | |
| 101 | |||
| 102 | ✗ | bt_hci_get_le_local_addr(&le_local); | |
| 103 | |||
| 104 | ✗ | memcpy(device->rand + 8, data, len); | |
| 105 | ✗ | smp_c1_part1(device, tk, device->rand, device->preq, device->pres, &le_local, &device->le_remote_bdaddr, device->ltk); | |
| 106 | ✗ | } | |
| 107 | |||
| 108 | ✗ | static void bt_smp_confirm_half(struct bt_dev *device, uint8_t *data, uint32_t len) { | |
| 109 | ✗ | bt_addr_le_t le_local; | |
| 110 | ✗ | uint8_t tk[16] = {0}; | |
| 111 | |||
| 112 | ✗ | bt_hci_get_le_local_addr(&le_local); | |
| 113 | |||
| 114 | ✗ | memcpy(device->ltk, data, len); | |
| 115 | ✗ | smp_c1_part2(device, tk, device->rand, device->preq, device->pres, &le_local, &device->le_remote_bdaddr, device->ltk); | |
| 116 | ✗ | } | |
| 117 | |||
| 118 | ✗ | static void bt_smp_confirm_complete(struct bt_dev *device, uint8_t *data, uint32_t len) { | |
| 119 | ✗ | memcpy(device->ltk, data, len); | |
| 120 | ✗ | bt_smp_pairing_confirm(device->acl_handle, device->ltk); | |
| 121 | ✗ | } | |
| 122 | |||
| 123 | ✗ | static void bt_smp_stk_complete(struct bt_dev *device, uint8_t *data, uint32_t len) { | |
| 124 | ✗ | memcpy(device->ltk, data, len); | |
| 125 | ✗ | bt_hci_start_encryption(device->acl_handle, 0, 0, device->ltk); | |
| 126 | ✗ | } | |
| 127 | |||
| 128 | ✗ | static void bt_smp_key_distribution(struct bt_dev *device) { | |
| 129 | /* Unused keys IFAICT, so just use ESP random function rather than BT ctrl one */ | ||
| 130 | ✗ | uint8_t tmp[16] = {0}; | |
| 131 | |||
| 132 | ✗ | if (device->ldist & BT_SMP_DIST_ENC_KEY) { | |
| 133 | ✗ | esp_fill_random(tmp, sizeof(tmp)); | |
| 134 | ✗ | bt_smp_encrypt_info(device->acl_handle, tmp); | |
| 135 | ✗ | esp_fill_random(tmp, sizeof(tmp)); | |
| 136 | ✗ | bt_smp_master_ident(device->acl_handle, tmp, tmp + 2); | |
| 137 | } | ||
| 138 | ✗ | if (device->ldist & BT_SMP_DIST_ID_KEY) { | |
| 139 | ✗ | bt_addr_le_t le_local; | |
| 140 | ✗ | bt_hci_get_le_local_addr(&le_local); | |
| 141 | ✗ | esp_fill_random(tmp, sizeof(tmp)); | |
| 142 | ✗ | bt_smp_ident_info(device->acl_handle, tmp); | |
| 143 | ✗ | bt_smp_ident_addr_info(device->acl_handle, &le_local); | |
| 144 | } | ||
| 145 | ✗ | if (device->ldist & BT_SMP_DIST_SIGN) { | |
| 146 | ✗ | esp_fill_random(tmp, sizeof(tmp)); | |
| 147 | ✗ | bt_smp_signing_info(device->acl_handle, tmp); | |
| 148 | } | ||
| 149 | |||
| 150 | ✗ | bt_att_hid_init(device); | |
| 151 | ✗ | } | |
| 152 | |||
| 153 | ✗ | static void bt_smp_cmd(uint16_t handle, uint8_t code, uint16_t len) { | |
| 154 | ✗ | uint16_t packet_len = (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE | |
| 155 | + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_smp_hdr) + len); | ||
| 156 | |||
| 157 | ✗ | bt_hci_pkt_tmp.h4_hdr.type = BT_HCI_H4_TYPE_ACL; | |
| 158 | |||
| 159 | ✗ | bt_hci_pkt_tmp.acl_hdr.handle = bt_acl_handle_pack(handle, BT_ACL_START_NO_FLUSH); | |
| 160 | ✗ | bt_hci_pkt_tmp.acl_hdr.len = packet_len - BT_HCI_H4_HDR_SIZE - BT_HCI_ACL_HDR_SIZE; | |
| 161 | |||
| 162 | ✗ | bt_hci_pkt_tmp.l2cap_hdr.len = bt_hci_pkt_tmp.acl_hdr.len - sizeof(bt_hci_pkt_tmp.l2cap_hdr); | |
| 163 | ✗ | bt_hci_pkt_tmp.l2cap_hdr.cid = BT_L2CAP_CID_SMP; | |
| 164 | |||
| 165 | ✗ | bt_hci_pkt_tmp.smp_hdr.code = code; | |
| 166 | |||
| 167 | ✗ | bt_host_txq_add((uint8_t *)&bt_hci_pkt_tmp, packet_len); | |
| 168 | ✗ | } | |
| 169 | |||
| 170 | ✗ | static void bt_smp_pairing_req(uint16_t handle, struct bt_smp_pairing *pairing_req) { | |
| 171 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 172 | |||
| 173 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, (uint8_t *)pairing_req, sizeof(*pairing_req)); | |
| 174 | |||
| 175 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_PAIRING_REQ, sizeof(*pairing_req)); | |
| 176 | ✗ | } | |
| 177 | |||
| 178 | ✗ | static void bt_smp_pairing_confirm(uint16_t handle, uint8_t val[16]) { | |
| 179 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 180 | |||
| 181 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, val, sizeof(struct bt_smp_pairing_confirm)); | |
| 182 | |||
| 183 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_PAIRING_CONFIRM, sizeof(struct bt_smp_pairing_confirm)); | |
| 184 | ✗ | } | |
| 185 | |||
| 186 | ✗ | static void bt_smp_pairing_random(uint16_t handle, uint8_t val[16]) { | |
| 187 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 188 | |||
| 189 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, val, sizeof(struct bt_smp_pairing_random)); | |
| 190 | |||
| 191 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_PAIRING_RANDOM, sizeof(struct bt_smp_pairing_random)); | |
| 192 | ✗ | } | |
| 193 | |||
| 194 | ✗ | static void bt_smp_encrypt_info(uint16_t handle, uint8_t ltk[16]) { | |
| 195 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 196 | |||
| 197 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, ltk, sizeof(struct bt_smp_encrypt_info)); | |
| 198 | |||
| 199 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_ENCRYPT_INFO, sizeof(struct bt_smp_pairing_random)); | |
| 200 | ✗ | } | |
| 201 | |||
| 202 | ✗ | static void bt_smp_master_ident(uint16_t handle, uint8_t ediv[2], uint8_t rand[8]) { | |
| 203 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 204 | |||
| 205 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, ediv, 2); | |
| 206 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data + 2, rand, 8); | |
| 207 | |||
| 208 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_MASTER_IDENT, sizeof(struct bt_smp_master_ident)); | |
| 209 | ✗ | } | |
| 210 | |||
| 211 | ✗ | static void bt_smp_ident_info(uint16_t handle, uint8_t irk[16]) { | |
| 212 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 213 | |||
| 214 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, irk, sizeof(struct bt_smp_ident_info)); | |
| 215 | |||
| 216 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_IDENT_INFO, sizeof(struct bt_smp_ident_info)); | |
| 217 | ✗ | } | |
| 218 | |||
| 219 | ✗ | static void bt_smp_ident_addr_info(uint16_t handle, bt_addr_le_t *le_bdaddr) { | |
| 220 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 221 | |||
| 222 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, le_bdaddr, sizeof(struct bt_smp_ident_addr_info)); | |
| 223 | |||
| 224 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_IDENT_ADDR_INFO, sizeof(struct bt_smp_ident_addr_info)); | |
| 225 | ✗ | } | |
| 226 | |||
| 227 | ✗ | static void bt_smp_signing_info(uint16_t handle, uint8_t csrk[16]) { | |
| 228 | ✗ | printf("# %s\n", __FUNCTION__); | |
| 229 | |||
| 230 | ✗ | memcpy(bt_hci_pkt_tmp.smp_data, csrk, sizeof(struct bt_smp_signing_info)); | |
| 231 | |||
| 232 | ✗ | bt_smp_cmd(handle, BT_SMP_CMD_SIGNING_INFO, sizeof(struct bt_smp_signing_info)); | |
| 233 | ✗ | } | |
| 234 | |||
| 235 | ✗ | void bt_smp_pairing_start(struct bt_dev *device) { | |
| 236 | ✗ | struct bt_smp_pairing pairing_req = { | |
| 237 | .io_capability = BT_SMP_IO_NO_INPUT_OUTPUT, | ||
| 238 | .oob_flag = BT_SMP_OOB_NOT_PRESENT, | ||
| 239 | .auth_req = BT_SMP_AUTH_BONDING, | ||
| 240 | .max_key_size = BT_SMP_MAX_ENC_KEY_SIZE, | ||
| 241 | .init_key_dist = BT_SMP_DIST_ID_KEY, | ||
| 242 | .resp_key_dist = BT_SMP_DIST_ENC_KEY, | ||
| 243 | }; | ||
| 244 | ✗ | device->preq[0] = BT_SMP_CMD_PAIRING_REQ; | |
| 245 | ✗ | memcpy(&device->preq[1], (uint8_t *)&pairing_req, sizeof(pairing_req)); | |
| 246 | ✗ | bt_smp_pairing_req(device->acl_handle, &pairing_req); | |
| 247 | ✗ | } | |
| 248 | |||
| 249 | ✗ | void bt_smp_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) { | |
| 250 | ✗ | switch (bt_hci_acl_pkt->smp_hdr.code) { | |
| 251 | ✗ | case BT_SMP_CMD_PAIRING_RSP: | |
| 252 | { | ||
| 253 | ✗ | struct bt_smp_pairing *pairing_rsp = (struct bt_smp_pairing *)bt_hci_acl_pkt->smp_data; | |
| 254 | ✗ | printf("# BT_SMP_CMD_PAIRING_RSP\n"); | |
| 255 | |||
| 256 | ✗ | device->ldist = pairing_rsp->init_key_dist; | |
| 257 | ✗ | device->rdist = pairing_rsp->resp_key_dist; | |
| 258 | ✗ | device->pres[0] = BT_SMP_CMD_PAIRING_RSP; | |
| 259 | ✗ | memcpy(&device->pres[1], (uint8_t *)pairing_rsp, sizeof(*pairing_rsp)); | |
| 260 | |||
| 261 | ✗ | bt_hci_get_random(device, bt_smp_mrand_half); | |
| 262 | ✗ | bt_hci_get_random(device, bt_smp_mrand_complete); | |
| 263 | ✗ | break; | |
| 264 | } | ||
| 265 | ✗ | case BT_SMP_CMD_PAIRING_CONFIRM: | |
| 266 | { | ||
| 267 | //struct bt_smp_pairing_confirm *pairing_confirm = (struct bt_smp_pairing_confirm *)bt_hci_acl_pkt->smp_data; | ||
| 268 | ✗ | printf("# BT_SMP_CMD_PAIRING_CONFIRM\n"); | |
| 269 | |||
| 270 | ✗ | bt_smp_pairing_random(device->acl_handle, device->rand); | |
| 271 | ✗ | break; | |
| 272 | } | ||
| 273 | ✗ | case BT_SMP_CMD_PAIRING_RANDOM: | |
| 274 | { | ||
| 275 | ✗ | uint8_t tk[16] = {0}; | |
| 276 | ✗ | struct bt_smp_pairing_random *pairing_random = (struct bt_smp_pairing_random *)bt_hci_acl_pkt->smp_data; | |
| 277 | ✗ | printf("# BT_SMP_CMD_PAIRING_RANDOM\n"); | |
| 278 | |||
| 279 | /* We should validate remote confirm here, but we are lazy */ | ||
| 280 | |||
| 281 | ✗ | memcpy(device->rrand, pairing_random->val, sizeof(device->rrand)); | |
| 282 | ✗ | smp_s1(device, tk, device->rrand, device->rand, device->ltk); | |
| 283 | |||
| 284 | ✗ | if (!device->rdist) { | |
| 285 | ✗ | bt_smp_key_distribution(device); | |
| 286 | } | ||
| 287 | ✗ | break; | |
| 288 | } | ||
| 289 | ✗ | case BT_SMP_CMD_PAIRING_FAIL: | |
| 290 | { | ||
| 291 | ✗ | struct bt_smp_pairing_fail *pairing_fail = (struct bt_smp_pairing_fail *)bt_hci_acl_pkt->smp_data; | |
| 292 | ✗ | printf("# BT_SMP_CMD_PAIRING_FAIL reason: %02X\n", pairing_fail->reason); | |
| 293 | ✗ | break; | |
| 294 | } | ||
| 295 | ✗ | case BT_SMP_CMD_ENCRYPT_INFO: | |
| 296 | { | ||
| 297 | ✗ | struct bt_smp_encrypt_info *encrypt_info = (struct bt_smp_encrypt_info *)bt_hci_acl_pkt->smp_data; | |
| 298 | ✗ | printf("# BT_SMP_CMD_ENCRYPT_INFO\n"); | |
| 299 | |||
| 300 | ✗ | bt_host_store_le_ltk(&device->le_remote_bdaddr, encrypt_info); | |
| 301 | ✗ | break; | |
| 302 | } | ||
| 303 | ✗ | case BT_SMP_CMD_MASTER_IDENT: | |
| 304 | { | ||
| 305 | ✗ | struct bt_smp_master_ident *master_ident = (struct bt_smp_master_ident *)bt_hci_acl_pkt->smp_data; | |
| 306 | ✗ | printf("# BT_SMP_CMD_MASTER_IDENT\n"); | |
| 307 | |||
| 308 | ✗ | device->rdist &= ~BT_SMP_DIST_ENC_KEY; | |
| 309 | |||
| 310 | ✗ | bt_host_store_le_ident(&device->le_remote_bdaddr, master_ident); | |
| 311 | |||
| 312 | ✗ | if (!device->rdist) { | |
| 313 | ✗ | bt_smp_key_distribution(device); | |
| 314 | } | ||
| 315 | |||
| 316 | ✗ | bt_hci_add_to_accept_list(&device->le_remote_bdaddr); | |
| 317 | ✗ | break; | |
| 318 | } | ||
| 319 | ✗ | case BT_SMP_CMD_IDENT_INFO: | |
| 320 | ✗ | printf("# BT_SMP_CMD_IDENT_INFO\n"); | |
| 321 | ✗ | break; | |
| 322 | ✗ | case BT_SMP_CMD_IDENT_ADDR_INFO: | |
| 323 | ✗ | printf("# BT_SMP_CMD_IDENT_ADDR_INFO\n"); | |
| 324 | |||
| 325 | ✗ | device->rdist &= ~BT_SMP_DIST_ID_KEY; | |
| 326 | |||
| 327 | ✗ | if (!device->rdist) { | |
| 328 | ✗ | bt_smp_key_distribution(device); | |
| 329 | } | ||
| 330 | break; | ||
| 331 | ✗ | case BT_SMP_CMD_SIGNING_INFO: | |
| 332 | ✗ | printf("# BT_SMP_CMD_SIGNING_INFO\n"); | |
| 333 | |||
| 334 | ✗ | device->rdist &= ~BT_SMP_DIST_SIGN; | |
| 335 | |||
| 336 | ✗ | if (!device->rdist) { | |
| 337 | ✗ | bt_smp_key_distribution(device); | |
| 338 | } | ||
| 339 | break; | ||
| 340 | ✗ | default: | |
| 341 | ✗ | printf("# Unsupported OPCODE: 0x%02X\n", bt_hci_acl_pkt->smp_hdr.code); | |
| 342 | } | ||
| 343 | ✗ | } | |
| 344 |