Esempio n. 1
0
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
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;
}
Esempio n. 10
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;
}