Exemplo n.º 1
0
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
{
	struct l2cap_conn *conn = hcon->l2cap_data;
	struct smp_chan *smp;
	__u8 authreq;

	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);

	/* This may be NULL if there's an unexpected disconnection */
	if (!conn)
		return 1;

	if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
		return 1;

	if (smp_sufficient_security(hcon, sec_level))
		return 1;

	if (hcon->link_mode & HCI_LM_MASTER)
		if (smp_ltk_encrypt(conn, sec_level))
			goto done;

	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
		return 0;

	smp = smp_chan_create(conn);
	if (!smp)
		return 1;

	authreq = seclevel_to_authreq(sec_level);

	/* Require MITM if IO Capability allows or the security level
	 * requires it.
	 */
	if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
	    sec_level > BT_SECURITY_MEDIUM)
		authreq |= SMP_AUTH_MITM;

	if (hcon->link_mode & HCI_LM_MASTER) {
		struct smp_cmd_pairing cp;

		build_pairing_cmd(conn, &cp, NULL, authreq);
		smp->preq[0] = SMP_CMD_PAIRING_REQ;
		memcpy(&smp->preq[1], &cp, sizeof(cp));

		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
	} else {
		struct smp_cmd_security_req cp;
		cp.auth_req = authreq;
		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
	}

	set_bit(SMP_FLAG_INITIATOR, &smp->smp_flags);

done:
	hcon->pending_sec_level = sec_level;

	return 0;
}
Exemplo n.º 2
0
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
{
	struct l2cap_conn *conn = hcon->l2cap_data;
	struct smp_chan *smp = conn->smp_chan;
	__u8 authreq;

	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);

	if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
		return 1;

	if (smp_sufficient_security(hcon, sec_level))
		return 1;

	if (hcon->link_mode & HCI_LM_MASTER)
		if (smp_ltk_encrypt(conn, sec_level))
			goto done;

	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
		return 0;

	smp = smp_chan_create(conn);
	if (!smp)
		return 1;

	authreq = seclevel_to_authreq(sec_level);

	if (hcon->link_mode & HCI_LM_MASTER) {
		struct smp_cmd_pairing cp;

		build_pairing_cmd(conn, &cp, NULL, authreq);
		smp->preq[0] = SMP_CMD_PAIRING_REQ;
		memcpy(&smp->preq[1], &cp, sizeof(cp));

		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
	} else {
		struct smp_cmd_security_req cp;
		cp.auth_req = authreq;
		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
	}

done:
	hcon->pending_sec_level = sec_level;

	return 0;
}
Exemplo n.º 3
0
static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
	struct smp_cmd_security_req *rp = (void *) skb->data;
	struct smp_cmd_pairing cp;
	struct hci_conn *hcon = conn->hcon;
	struct smp_chan *smp;
	u8 sec_level;

	BT_DBG("conn %p", conn);

	sec_level = authreq_to_seclevel(rp->auth_req);
	if (smp_sufficient_security(hcon, sec_level))
		return 0;

	if (sec_level > hcon->pending_sec_level)
		hcon->pending_sec_level = sec_level;

	if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
		return 0;

	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
		return 0;

	smp = smp_chan_create(conn);
	if (!smp)
		return SMP_UNSPECIFIED;

	skb_pull(skb, sizeof(*rp));

	memset(&cp, 0, sizeof(cp));
	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);

	smp->preq[0] = SMP_CMD_PAIRING_REQ;
	memcpy(&smp->preq[1], &cp, sizeof(cp));

	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);

	return 0;
}