Пример #1
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];

	/* The responder sends its keys first */
	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;

		/* Send a dummy key */
		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));

		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);

		/* Just public address */
		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;

		/* Send a dummy key */
		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);
#ifdef BLUETOOTH_CUSTOMIZE
		clear_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &hcon->pend);
#endif /* BLUETOOTH_CUSTOMIZE */
		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);
#ifdef BLUETOOTH_CUSTOMIZE
		clear_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &hcon->pend);
#endif /* BLUETOOTH_CUSTOMIZE */
		mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
		hci_conn_put(hcon);
	}

	return 0;
}
Пример #2
0
/* Connect Complete */
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
	struct hci_conn *conn, *pend;

	BT_DBG("%s", hdev->name);

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
	if (!conn) {
		hci_dev_unlock(hdev);
		return;
	}

	if (!ev->status) {
		conn->handle = __le16_to_cpu(ev->handle);
		conn->state  = BT_CONNECTED;

		if (test_bit(HCI_AUTH, &hdev->flags))
			conn->link_mode |= HCI_LM_AUTH;

		if (test_bit(HCI_ENCRYPT, &hdev->flags))
			conn->link_mode |= HCI_LM_ENCRYPT;

		/* Get remote features */
		if (conn->type == ACL_LINK) {
			struct hci_cp_read_remote_features cp;
			cp.handle = ev->handle;
			hci_send_cmd(hdev, OGF_LINK_CTL,
				OCF_READ_REMOTE_FEATURES, sizeof(cp), &cp);
		}

		/* Set link policy */
		if (conn->type == ACL_LINK && hdev->link_policy) {
			struct hci_cp_write_link_policy cp;
			cp.handle = ev->handle;
			cp.policy = __cpu_to_le16(hdev->link_policy);
			hci_send_cmd(hdev, OGF_LINK_POLICY,
				OCF_WRITE_LINK_POLICY, sizeof(cp), &cp);
		}

		/* Set packet type for incoming connection */
		if (!conn->out) {
			struct hci_cp_change_conn_ptype cp;
			cp.handle = ev->handle;
			cp.pkt_type = (conn->type == ACL_LINK) ?
				__cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):
				__cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);

			hci_send_cmd(hdev, OGF_LINK_CTL,
				OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);
		} else {
			/* Update disconnect timer */
			hci_conn_hold(conn);
			hci_conn_put(conn);
		}
	} else
		conn->state = BT_CLOSED;

	if (conn->type == ACL_LINK) {
		struct hci_conn *sco = conn->link;
		if (sco) {
			if (!ev->status)
				hci_add_sco(sco, conn->handle);
			else {
				hci_proto_connect_cfm(sco, ev->status);
				hci_conn_del(sco);
			}
		}
	}

	hci_proto_connect_cfm(conn, ev->status);
	if (ev->status)
		hci_conn_del(conn);

	pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
	if (pend)
		hci_acl_connect(pend);

	hci_dev_unlock(hdev);
}
Пример #3
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);
#ifdef BLUETOOTH_CUSTOMIZE
		clear_bit(HCI_CONN_LE_CONN_UPDATE_PEND, &hcon->pend);
#endif /* BLUETOOTH_CUSTOMIZE */
		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:
		/* Just ignored */
		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);
#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);
	}

	kfree_skb(skb);
	return err;
}
Пример #4
0
void smp_chan_destroy(struct l2cap_conn *conn)
{
	kfree(conn->smp_chan);
	hci_conn_put(conn->hcon);
}
Пример #5
0
static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct hci_ev_remote_features *ev = (void *) skb->data;
	struct hci_conn *conn;

	BT_DBG("%s status %d", hdev->name, ev->status);

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
	if (conn) {
		if (!ev->status)
			memcpy(conn->features, ev->features, 8);

		if (conn->state == BT_CONFIG) {
			if (!ev->status && lmp_ssp_capable(hdev) &&
						lmp_ssp_capable(conn)) {
				struct hci_cp_read_remote_ext_features cp;
				cp.handle = ev->handle;
				cp.page = 0x01;
				hci_send_cmd(hdev,
					HCI_OP_READ_REMOTE_EXT_FEATURES,
							sizeof(cp), &cp);
			} else {
                if (!(conn->features[3]&(0x02|0x04)))   /* not support 2M/3M EDR. 0x02=2M  0x04=3M */
                {                    
                    if (!(conn->link_mode & HCI_LM_MASTER)) /* act as slave */
                    {                        
                        if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) 
                        {
                            struct hci_cp_switch_role cp;
                            cp.bdaddr.b[0]= 0;    /* init */
                            cp.bdaddr.b[1]= 0;
                            cp.bdaddr.b[2]= 0;
                            cp.bdaddr.b[3]= 0;
                            cp.bdaddr.b[4]= 0;
                            cp.bdaddr.b[5]= 0;
                            cp.role = 0;

                            bacpy(&cp.bdaddr, &conn->dst);
                            /* switch to master */
                            cp.role = 0x0; 
                            BT_DBG("switch to master");
                            hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
                        }
                    }
                    else 
                    {
                        struct hci_cp_write_link_policy cp;
                        cp.handle = 0; /* init */
                        cp.policy = 0;

                        /* disable role_switch if already act as master */
                        cp.handle = cpu_to_le16(conn->handle);
                        conn->link_policy |= HCI_LP_SNIFF;
                        conn->link_policy |= HCI_LP_HOLD;
                        conn->link_policy &= ~HCI_LP_RSWITCH;
                        cp.policy = cpu_to_le16(conn->link_policy);
                        hci_send_cmd(conn->hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp);
                    }
                }                        
				conn->state = BT_CONNECTED;
				hci_proto_connect_cfm(conn, ev->status);
				hci_conn_put(conn);
			}
		}
	}

	hci_dev_unlock(hdev);
}
Пример #6
0
static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct hci_ev_auth_complete *ev = (void *) skb->data;
	struct hci_conn *conn;

	BT_DBG("%s status %d", hdev->name, ev->status);

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
	if (conn) {
		if (!ev->status)
			conn->link_mode |= HCI_LM_AUTH;
		else
			conn->sec_level = BT_SECURITY_LOW;
			
		//modify the problem of PIN or KEY MISSIMG  ZTE_BT_QXX_20101118 begin		
		if (ev->status == 0x06 && hdev->ssp_mode > 0 &&
                                       conn->ssp_mode > 0 && conn->out) { // PIN or KEY MISSING
                       struct hci_cp_auth_requested cp;
                       cp.handle = ev->handle;
                       hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
                                               sizeof(cp), &cp);
                       goto done;
               }
    //modify the problem of PIN or KEY MISSIMG  ZTE_BT_QXX_20101118 end
		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);

		if (conn->state == BT_CONFIG) {
			if (!ev->status && hdev->ssp_mode > 0 &&
							conn->ssp_mode > 0) {
				struct hci_cp_set_conn_encrypt cp;
				cp.handle  = ev->handle;
				cp.encrypt = 0x01;
				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
							sizeof(cp), &cp);
			} else {
				conn->state = BT_CONNECTED;
				hci_proto_connect_cfm(conn, ev->status);
				hci_conn_put(conn);
			}
		} else {
			hci_auth_cfm(conn, ev->status);

			hci_conn_hold(conn);
			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
			hci_conn_put(conn);
		}

		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
			if (!ev->status) {
				struct hci_cp_set_conn_encrypt cp;
				cp.handle  = ev->handle;
				cp.encrypt = 0x01;
				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
							sizeof(cp), &cp);
			} else {
				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
				hci_encrypt_cfm(conn, ev->status, 0x00);
			}
		}
	}
	
//modify the problem of PIN or KEY MISSIMG  ZTE_BT_QXX_20101118
done:   
	hci_dev_unlock(hdev);
}
Пример #7
0
static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
	struct hci_ev_auth_complete *ev = (void *) skb->data;
	struct hci_conn *conn;

	BT_DBG("%s status %d", hdev->name, ev->status);

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
	if (conn) {
		if (!ev->status)
			conn->link_mode |= HCI_LM_AUTH;
		else
			conn->sec_level = BT_SECURITY_LOW;
// BEGIN SS_BLUEZ_BT +kjh 2011.03.17 : 
// workaround for nobonding. 
// cond 1. local has link key. remote doesn't have link key.
// cond 2. local & remote are ssp mode
// cond 3. send opp file from local to remote
// result -> pin or key missing err returned.
// so send "HCI_OP_AUTH_REQUESTED" one more time. 
		if (ev->status == 0x06 && hdev->ssp_mode > 0 &&  // 0x06 Error code (PIN or key missing)
				conn->ssp_mode > 0 && conn->out) { // hdev: remote device, conn: connection 
			struct hci_cp_auth_requested cp;
			cp.handle = ev->handle;
			hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
				sizeof(cp), &cp);
			printk(KERN_ERR "error code = 0x06, sspmode => HCI_OP_AUTH_REQUESTED");
			goto done;
		}
// END SS_BLUEZ_BT	
		
		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);

		if (conn->state == BT_CONFIG) {
			if (!ev->status && hdev->ssp_mode > 0 &&
							conn->ssp_mode > 0) {
				struct hci_cp_set_conn_encrypt cp;
				cp.handle  = ev->handle;
				cp.encrypt = 0x01;
				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
							sizeof(cp), &cp);
			} else {
				conn->state = BT_CONNECTED;
				hci_proto_connect_cfm(conn, ev->status);
				hci_conn_put(conn);
			}
		} else {
			hci_auth_cfm(conn, ev->status);

			hci_conn_hold(conn);
			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
			hci_conn_put(conn);
		}

		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
			if (!ev->status) {
				struct hci_cp_set_conn_encrypt cp;
				cp.handle  = ev->handle;
				cp.encrypt = 0x01;
				hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
							sizeof(cp), &cp);
			} else {
				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
				hci_encrypt_cfm(conn, ev->status, 0x00);
			}
		}
	}

// BEGIN SS_BLUEZ_BT +kjh 2011.03.17 : 
done:
// END SS_BLUEZ_BT	

	hci_dev_unlock(hdev);
}