static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_ident_addr_info *info = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; struct hci_conn *hcon = conn->hcon; bdaddr_t rpa; BT_DBG(""); if (skb->len < sizeof(*info)) return SMP_UNSPECIFIED; /* Ignore this PDU if it wasn't requested */ if (!(smp->remote_key_dist & SMP_DIST_ID_KEY)) return 0; /* Mark the information as received */ smp->remote_key_dist &= ~SMP_DIST_ID_KEY; skb_pull(skb, sizeof(*info)); /* Strictly speaking the Core Specification (4.1) allows sending * an empty address which would force us to rely on just the IRK * as "identity information". However, since such * implementations are not known of and in order to not over * complicate our implementation, simply pretend that we never * received an IRK for such a device. */ if (!bacmp(&info->bdaddr, BDADDR_ANY)) { BT_ERR("Ignoring IRK with no identity address"); smp_distribute_keys(conn); return 0; } bacpy(&smp->id_addr, &info->bdaddr); smp->id_addr_type = info->addr_type; if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type)) bacpy(&rpa, &hcon->dst); else bacpy(&rpa, BDADDR_ANY); smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, smp->id_addr_type, smp->irk, &rpa); smp_distribute_keys(conn); return 0; }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct hci_conn *hcon = conn->hcon; struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1]; struct link_key *key; u8 *keydist; skb_pull(skb, sizeof(*rp)); key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK); if (key == NULL) return SMP_UNSPECIFIED; if (hcon->out) keydist = &paircmd->resp_key_dist; else keydist = &paircmd->init_key_dist; BT_DBG("keydist 0x%x", *keydist); hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type, hcon->smp_key_size, hcon->auth, rp->ediv, rp->rand, key->val); *keydist &= ~SMP_DIST_ENC_KEY; if (hcon->out) { if (!(*keydist)) smp_distribute_keys(conn, 1); } return 0; }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_cmd_pairing *paircmd = (void *) &conn->prsp[1]; struct link_key *key; struct key_master_id *id; u8 keydist = paircmd->init_key_dist; skb_pull(skb, sizeof(*rp)); key = hci_find_link_key_type(conn->hcon->hdev, conn->dst, KEY_TYPE_LTK); if (key == NULL) return SMP_UNSPECIFIED; BT_DBG("keydist 0x%x", keydist); id = (void *) key->data; id->ediv = rp->ediv; memcpy(id->rand, rp->rand, sizeof(rp->rand)); hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size, rp->ediv, rp->rand, key->val); smp_distribute_keys(conn, 1); return 0; }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; struct hci_dev *hdev = conn->hcon->hdev; struct hci_conn *hcon = conn->hcon; struct smp_ltk *ltk; u8 authenticated; BT_DBG("conn %p", conn); if (skb->len < sizeof(*rp)) return SMP_UNSPECIFIED; /* Ignore this PDU if it wasn't requested */ if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY)) return 0; /* Mark the information as received */ smp->remote_key_dist &= ~SMP_DIST_ENC_KEY; skb_pull(skb, sizeof(*rp)); hci_dev_lock(hdev); authenticated = (hcon->sec_level == BT_SECURITY_HIGH); ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, authenticated, smp->tk, smp->enc_key_size, rp->ediv, rp->rand); smp->ltk = ltk; if (!(smp->remote_key_dist & SMP_DIST_ID_KEY)) smp_distribute_keys(conn); hci_dev_unlock(hdev); return 0; }
static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_sign_info *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; struct hci_dev *hdev = conn->hcon->hdev; struct smp_csrk *csrk; BT_DBG("conn %p", conn); if (skb->len < sizeof(*rp)) return SMP_UNSPECIFIED; /* Ignore this PDU if it wasn't requested */ if (!(smp->remote_key_dist & SMP_DIST_SIGN)) return 0; /* Mark the information as received */ smp->remote_key_dist &= ~SMP_DIST_SIGN; skb_pull(skb, sizeof(*rp)); hci_dev_lock(hdev); csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); if (csrk) { csrk->master = 0x01; memcpy(csrk->val, rp->csrk, sizeof(csrk->val)); } smp->csrk = csrk; if (!(smp->remote_key_dist & SMP_DIST_SIGN)) smp_distribute_keys(conn); hci_dev_unlock(hdev); return 0; }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; skb_pull(skb, sizeof(*rp)); hci_add_ltk(conn->hcon->hdev, 1, conn->src, conn->smp_key_size, rp->ediv, rp->rand, conn->tk); smp_distribute_keys(conn, 1); return 0; }
int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt) { struct hci_conn *hcon = conn->hcon; BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req); if (!status && encrypt && !hcon->sec_req) smp_distribute_keys(conn, 0); /* Fall back to Pairing request if failed a Link Security request */ else if (hcon->sec_req && (status || !encrypt)) smp_conn_security(conn, hcon->sec_level); return 0; }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; struct hci_dev *hdev = conn->hcon->hdev; struct hci_conn *hcon = conn->hcon; u8 authenticated; skb_pull(skb, sizeof(*rp)); hci_dev_lock(hdev); authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, rp->ediv, rp->rand); smp_distribute_keys(conn, 1); hci_dev_unlock(hdev); return 0; }
int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt) { struct hci_conn *hcon = conn->hcon; BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level) hcon->sec_level = hcon->pending_sec_level; if (!status && encrypt && !hcon->sec_req) return smp_distribute_keys(conn, 0); else if (hcon->sec_req && (status || !encrypt)) smp_conn_security(conn, hcon->pending_sec_level); hci_conn_put(hcon); return 0; }
int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt) { struct hci_conn *hcon = conn->hcon; BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); #ifdef BLUETOOTH_CUSTOMIZE if (test_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &hcon->pend)) { struct sock *sk; BT_DBG("HCI_CONN_LE_CONN_UPDATE_PEND"); sk = l2cap_find_sock_by_fixed_cid_and_dir(4, conn->src, conn->dst, 0); if (sk) { BT_DBG("call hci_le_conn_update"); hci_le_conn_update(hcon, bt_sk(sk)->le_params.interval_min, bt_sk(sk)->le_params.interval_max, bt_sk(sk)->le_params.latency, bt_sk(sk)->le_params.supervision_timeout); } } #endif /* BLUETOOTH_CUSTOMIZE */ if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level) hcon->sec_level = hcon->pending_sec_level; if (!status && encrypt && !hcon->sec_req) return smp_distribute_keys(conn, 0); /* Fall back to Pairing request if failed a Link Security request */ else if (hcon->sec_req && (status || !encrypt)) smp_conn_security(conn, hcon->pending_sec_level); hci_conn_put(hcon); return 0; }