static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) { struct hci_conn *hcon = conn->hcon; int ret; BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf)); skb_pull(skb, sizeof(hcon->pcnf)); if (conn->hcon->out) { u8 random[16]; swap128(hcon->prnd, random); smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), random); } else if (hcon->tk_valid) { ret = send_pairing_confirm(conn); if (ret) return SMP_CONFIRM_FAILED; } else hcon->cfm_pending = TRUE; mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT)); return 0; }
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 u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) { struct hci_conn *hcon = conn->hcon; struct smp_cmd_pairing *req, *rsp = (void *) skb->data; u8 key_size, auth = SMP_AUTH_NONE; int ret; BT_DBG("conn %p", conn); skb_pull(skb, sizeof(*rsp)); req = (void *) &hcon->preq[1]; key_size = min(req->max_key_size, rsp->max_key_size); if (check_enc_key_size(conn, key_size)) return SMP_ENC_KEY_SIZE; hcon->prsp[0] = SMP_CMD_PAIRING_RSP; memcpy(&hcon->prsp[1], rsp, sizeof(*rsp)); ret = smp_rand(hcon->prnd); if (ret) return SMP_UNSPECIFIED; if ((req->auth_req & SMP_AUTH_BONDING) && (rsp->auth_req & SMP_AUTH_BONDING)) auth = SMP_AUTH_BONDING; auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability, req->io_capability); if (ret) return SMP_UNSPECIFIED; hcon->cfm_pending = TRUE; if (!hcon->tk_valid) return 0; ret = send_pairing_confirm(conn); if (ret) return SMP_CONFIRM_FAILED; return 0; }