Exemple #1
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);
	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);
}
Exemple #3
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);
	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);
}
Exemple #4
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);
}
Exemple #5
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;
}
Exemple #6
0
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);
	}
}
Exemple #8
0
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;
	}
}
Exemple #9
0
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;
}
Exemple #10
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;
}