void smp_timeout(unsigned long arg) { struct l2cap_conn *conn = (void *) arg; u8 reason = SMP_UNSPECIFIED; BT_DBG("%p", conn); smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED); hci_conn_put(conn->hcon); }
static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) { if (send) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); del_timer(&conn->security_timer); smp_chan_destroy(conn); }
void smp_timeout(unsigned long arg) { struct l2cap_conn *conn = (void *) arg; u8 reason = SMP_UNSPECIFIED; BT_DBG("%p", conn); smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED); hci_conn_put(conn->hcon); //delete the l2cap connection l2cap_conn_del(conn->hcon, EACCES, 0); }
void smp_timeout(unsigned long arg) { struct l2cap_conn *conn = (void *) arg; u8 reason = SMP_UNSPECIFIED; BT_DBG("%p", conn); smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); #ifdef BLUETOOTH_CUSTOMIZE clear_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &conn->hcon->pend); #endif /* BLUETOOTH_CUSTOMIZE */ mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED); hci_conn_put(conn->hcon); }
int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp) { struct mgmt_cp_user_passkey_reply *psk_reply = cp; struct l2cap_conn *conn = hcon->smp_conn; u8 key[16]; u8 reason = 0; int ret = 0; BT_DBG(""); hcon->tk_valid = TRUE; switch (mgmt_op) { case MGMT_OP_USER_CONFIRM_NEG_REPLY: reason = SMP_CONFIRM_FAILED; break; case MGMT_OP_USER_CONFIRM_REPLY: break; case MGMT_OP_USER_PASSKEY_REPLY: memset(key, 0, sizeof(key)); BT_DBG("PassKey: %d", psk_reply->passkey); put_unaligned_le32(psk_reply->passkey, key); swap128(key, hcon->tk); break; default: reason = SMP_CONFIRM_FAILED; ret = -EOPNOTSUPP; break; } if (reason) { BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL"); smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); del_timer(&hcon->smp_timer); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); #ifdef BLUETOOTH_CUSTOMIZE clear_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &hcon->pend); #endif /* BLUETOOTH_CUSTOMIZE */ mgmt_auth_failed(hcon->hdev->id, conn->dst, reason); hci_conn_put(hcon); } else if (hcon->cfm_pending) { BT_DBG("send_pairing_confirm"); ret = send_pairing_confirm(conn); } return ret; }
static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) { struct hci_conn *hcon = conn->hcon; if (send) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, hcon->dst_type, HCI_ERROR_AUTH_FAILURE); cancel_delayed_work_sync(&conn->security_timer); if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) smp_chan_destroy(conn); }
static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) { struct hci_conn *hcon = conn->hcon; if (send) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, hcon->dst_type, reason); if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { /* SSBT :: NEO (0213) */ /*del_timer(&conn->security_timer); */ del_timer_sync(&conn->security_timer); smp_chan_destroy(conn); } }
void control_message(uint16_t opcode, const void *data, uint16_t size) { if (!decode_control) return; switch (opcode) { case MGMT_EV_INDEX_ADDED: mgmt_index_added(size, data); break; case MGMT_EV_INDEX_REMOVED: mgmt_index_removed(size, data); break; case MGMT_EV_CONTROLLER_ERROR: mgmt_controller_error(size, data); break; case MGMT_EV_NEW_SETTINGS: mgmt_new_settings(size, data); break; case MGMT_EV_CLASS_OF_DEV_CHANGED: mgmt_class_of_dev_changed(size, data); break; case MGMT_EV_LOCAL_NAME_CHANGED: mgmt_local_name_changed(size, data); break; case MGMT_EV_NEW_LINK_KEY: mgmt_new_link_key(size, data); break; case MGMT_EV_NEW_LONG_TERM_KEY: mgmt_new_long_term_key(size, data); break; case MGMT_EV_DEVICE_CONNECTED: mgmt_device_connected(size, data); break; case MGMT_EV_DEVICE_DISCONNECTED: mgmt_device_disconnected(size, data); break; case MGMT_EV_CONNECT_FAILED: mgmt_connect_failed(size, data); break; case MGMT_EV_PIN_CODE_REQUEST: mgmt_pin_code_request(size, data); break; case MGMT_EV_USER_CONFIRM_REQUEST: mgmt_user_confirm_request(size, data); break; case MGMT_EV_USER_PASSKEY_REQUEST: mgmt_user_passkey_request(size, data); break; case MGMT_EV_AUTH_FAILED: mgmt_auth_failed(size, data); break; case MGMT_EV_DEVICE_FOUND: mgmt_device_found(size, data); break; case MGMT_EV_DISCOVERING: mgmt_discovering(size, data); break; case MGMT_EV_DEVICE_BLOCKED: mgmt_device_blocked(size, data); break; case MGMT_EV_DEVICE_UNBLOCKED: mgmt_device_unblocked(size, data); break; case MGMT_EV_DEVICE_UNPAIRED: mgmt_device_unpaired(size, data); break; case MGMT_EV_PASSKEY_NOTIFY: mgmt_passkey_notify(size, data); break; case MGMT_EV_NEW_IRK: mgmt_new_irk(size, data); break; case MGMT_EV_NEW_CSRK: mgmt_new_csrk(size, data); break; case MGMT_EV_DEVICE_ADDED: mgmt_device_added(size, data); break; case MGMT_EV_DEVICE_REMOVED: mgmt_device_removed(size, data); break; case MGMT_EV_NEW_CONN_PARAM: mgmt_new_conn_param(size, data); break; case MGMT_EV_UNCONF_INDEX_ADDED: mgmt_unconf_index_added(size, data); break; case MGMT_EV_UNCONF_INDEX_REMOVED: mgmt_unconf_index_removed(size, data); break; case MGMT_EV_NEW_CONFIG_OPTIONS: mgmt_new_config_options(size, data); break; case MGMT_EV_EXT_INDEX_ADDED: mgmt_ext_index_added(size, data); break; case MGMT_EV_EXT_INDEX_REMOVED: mgmt_ext_index_removed(size, data); break; case MGMT_EV_ADVERTISING_ADDED: mgmt_advertising_added(size, data); break; case MGMT_EV_ADVERTISING_REMOVED: mgmt_advertising_removed(size, data); break; default: printf("* Unknown control (code %d len %d)\n", opcode, size); packet_hexdump(data, size); break; } }
static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) { struct hci_conn *hcon = conn->hcon; struct smp_cmd_pairing *req, *rsp; __u8 *keydist; BT_DBG("conn %p force %d", conn, force); if (IS_ERR(hcon->hdev->tfm)) return PTR_ERR(hcon->hdev->tfm); rsp = (void *) &hcon->prsp[1]; if (!force && hcon->out && (rsp->resp_key_dist & 0x07)) return 0; req = (void *) &hcon->preq[1]; if (hcon->out) { keydist = &rsp->init_key_dist; *keydist &= req->init_key_dist; } else { keydist = &rsp->resp_key_dist; *keydist &= req->resp_key_dist; } BT_DBG("keydist 0x%x", *keydist); if (*keydist & SMP_DIST_ENC_KEY) { struct smp_cmd_encrypt_info enc; struct smp_cmd_master_ident ident; __le16 ediv; get_random_bytes(enc.ltk, sizeof(enc.ltk)); get_random_bytes(&ediv, sizeof(ediv)); get_random_bytes(ident.rand, sizeof(ident.rand)); smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type, hcon->smp_key_size, hcon->auth, ediv, ident.rand, enc.ltk); ident.ediv = cpu_to_le16(ediv); smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); *keydist &= ~SMP_DIST_ENC_KEY; } if (*keydist & SMP_DIST_ID_KEY) { struct smp_cmd_ident_addr_info addrinfo; struct smp_cmd_ident_info idinfo; get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); memset(&addrinfo, 0, sizeof(addrinfo)); bacpy(&addrinfo.bdaddr, conn->src); smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), &addrinfo); *keydist &= ~SMP_DIST_ID_KEY; } if (*keydist & SMP_DIST_SIGN) { struct smp_cmd_sign_info sign; get_random_bytes(sign.csrk, sizeof(sign.csrk)); smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); *keydist &= ~SMP_DIST_SIGN; } if (hcon->out) { if (hcon->disconn_cfm_cb) hcon->disconn_cfm_cb(hcon, 0); del_timer(&hcon->smp_timer); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); hci_conn_put(hcon); } else if (rsp->resp_key_dist) { if (hcon->disconn_cfm_cb) hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED); hci_conn_put(hcon); } return 0; }
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) { struct hci_conn *hcon = conn->hcon; __u8 code = skb->data[0]; __u8 reason; int err = 0; if (IS_ERR(hcon->hdev->tfm)) { err = PTR_ERR(hcon->hdev->tfm); reason = SMP_PAIRING_NOTSUPP; BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm); goto done; } hcon->smp_conn = conn; skb_pull(skb, sizeof(code)); switch (code) { case SMP_CMD_PAIRING_REQ: reason = smp_cmd_pairing_req(conn, skb); break; case SMP_CMD_PAIRING_FAIL: reason = 0; err = -EPERM; del_timer(&hcon->smp_timer); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]); hci_conn_put(hcon); break; case SMP_CMD_PAIRING_RSP: reason = smp_cmd_pairing_rsp(conn, skb); break; case SMP_CMD_SECURITY_REQ: reason = smp_cmd_security_req(conn, skb); break; case SMP_CMD_PAIRING_CONFIRM: reason = smp_cmd_pairing_confirm(conn, skb); break; case SMP_CMD_PAIRING_RANDOM: reason = smp_cmd_pairing_random(conn, skb); break; case SMP_CMD_ENCRYPT_INFO: reason = smp_cmd_encrypt_info(conn, skb); break; case SMP_CMD_MASTER_IDENT: reason = smp_cmd_master_ident(conn, skb); break; case SMP_CMD_IDENT_INFO: case SMP_CMD_IDENT_ADDR_INFO: case SMP_CMD_SIGN_INFO: reason = 0; break; default: BT_DBG("Unknown command code 0x%2.2x", code); reason = SMP_CMD_NOTSUPP; err = -EOPNOTSUPP; goto done; } done: if (reason) { BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason); smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); del_timer(&hcon->smp_timer); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); mgmt_auth_failed(hcon->hdev->id, conn->dst, reason); hci_conn_put(hcon); } kfree_skb(skb); return err; }
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data) { char buf[MGMT_BUF_SIZE]; struct mgmt_hdr *hdr = (void *) buf; int sk; ssize_t ret; uint16_t len, opcode, index; DBG("cond %d", cond); if (cond & G_IO_NVAL) return FALSE; sk = g_io_channel_unix_get_fd(io); if (cond & (G_IO_ERR | G_IO_HUP)) { error("Error on management socket"); return FALSE; } ret = read(sk, buf, sizeof(buf)); if (ret < 0) { error("Unable to read from management socket: %s (%d)", strerror(errno), errno); return TRUE; } DBG("Received %zd bytes from management socket", ret); if (ret < MGMT_HDR_SIZE) { error("Too small Management packet"); return TRUE; } opcode = btohs(bt_get_unaligned(&hdr->opcode)); len = btohs(bt_get_unaligned(&hdr->len)); index = btohs(bt_get_unaligned(&hdr->index)); if (ret != MGMT_HDR_SIZE + len) { error("Packet length mismatch. ret %zd len %u", ret, len); return TRUE; } switch (opcode) { case MGMT_EV_CMD_COMPLETE: mgmt_cmd_complete(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CMD_STATUS: mgmt_cmd_status(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONTROLLER_ERROR: mgmt_controller_error(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_INDEX_ADDED: mgmt_index_added(sk, index); break; case MGMT_EV_INDEX_REMOVED: mgmt_index_removed(sk, index); break; case MGMT_EV_POWERED: mgmt_powered(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DISCOVERABLE: mgmt_discoverable(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECTABLE: mgmt_connectable(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PAIRABLE: mgmt_pairable(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_NEW_KEY: mgmt_new_key(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_CONNECTED: mgmt_device_connected(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_DISCONNECTED: mgmt_device_disconnected(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECT_FAILED: mgmt_connect_failed(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PIN_CODE_REQUEST: mgmt_pin_code_request(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_USER_CONFIRM_REQUEST: mgmt_user_confirm_request(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_AUTH_FAILED: mgmt_auth_failed(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_LOCAL_NAME_CHANGED: mgmt_local_name_changed(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_FOUND: mgmt_device_found(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_REMOTE_NAME: mgmt_remote_name(sk, index, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DISCOVERING: mgmt_discovering(sk, index, buf + MGMT_HDR_SIZE, len); break; default: error("Unknown Management opcode %u (index %u)", opcode, index); break; } return TRUE; }