cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amp.c (14203B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3   Copyright (c) 2011,2012 Intel Corp.
      4
      5*/
      6
      7#include <net/bluetooth/bluetooth.h>
      8#include <net/bluetooth/hci.h>
      9#include <net/bluetooth/hci_core.h>
     10#include <crypto/hash.h>
     11
     12#include "hci_request.h"
     13#include "a2mp.h"
     14#include "amp.h"
     15
     16/* Remote AMP Controllers interface */
     17void amp_ctrl_get(struct amp_ctrl *ctrl)
     18{
     19	BT_DBG("ctrl %p orig refcnt %d", ctrl,
     20	       kref_read(&ctrl->kref));
     21
     22	kref_get(&ctrl->kref);
     23}
     24
     25static void amp_ctrl_destroy(struct kref *kref)
     26{
     27	struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
     28
     29	BT_DBG("ctrl %p", ctrl);
     30
     31	kfree(ctrl->assoc);
     32	kfree(ctrl);
     33}
     34
     35int amp_ctrl_put(struct amp_ctrl *ctrl)
     36{
     37	BT_DBG("ctrl %p orig refcnt %d", ctrl,
     38	       kref_read(&ctrl->kref));
     39
     40	return kref_put(&ctrl->kref, &amp_ctrl_destroy);
     41}
     42
     43struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id)
     44{
     45	struct amp_ctrl *ctrl;
     46
     47	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
     48	if (!ctrl)
     49		return NULL;
     50
     51	kref_init(&ctrl->kref);
     52	ctrl->id = id;
     53
     54	mutex_lock(&mgr->amp_ctrls_lock);
     55	list_add(&ctrl->list, &mgr->amp_ctrls);
     56	mutex_unlock(&mgr->amp_ctrls_lock);
     57
     58	BT_DBG("mgr %p ctrl %p", mgr, ctrl);
     59
     60	return ctrl;
     61}
     62
     63void amp_ctrl_list_flush(struct amp_mgr *mgr)
     64{
     65	struct amp_ctrl *ctrl, *n;
     66
     67	BT_DBG("mgr %p", mgr);
     68
     69	mutex_lock(&mgr->amp_ctrls_lock);
     70	list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
     71		list_del(&ctrl->list);
     72		amp_ctrl_put(ctrl);
     73	}
     74	mutex_unlock(&mgr->amp_ctrls_lock);
     75}
     76
     77struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
     78{
     79	struct amp_ctrl *ctrl;
     80
     81	BT_DBG("mgr %p id %u", mgr, id);
     82
     83	mutex_lock(&mgr->amp_ctrls_lock);
     84	list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
     85		if (ctrl->id == id) {
     86			amp_ctrl_get(ctrl);
     87			mutex_unlock(&mgr->amp_ctrls_lock);
     88			return ctrl;
     89		}
     90	}
     91	mutex_unlock(&mgr->amp_ctrls_lock);
     92
     93	return NULL;
     94}
     95
     96/* Physical Link interface */
     97static u8 __next_handle(struct amp_mgr *mgr)
     98{
     99	if (++mgr->handle == 0)
    100		mgr->handle = 1;
    101
    102	return mgr->handle;
    103}
    104
    105struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
    106			     u8 remote_id, bool out)
    107{
    108	bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst;
    109	struct hci_conn *hcon;
    110	u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
    111
    112	hcon = hci_conn_add(hdev, AMP_LINK, dst, role);
    113	if (!hcon)
    114		return NULL;
    115
    116	BT_DBG("hcon %p dst %pMR", hcon, dst);
    117
    118	hcon->state = BT_CONNECT;
    119	hcon->attempt++;
    120	hcon->handle = __next_handle(mgr);
    121	hcon->remote_id = remote_id;
    122	hcon->amp_mgr = amp_mgr_get(mgr);
    123
    124	return hcon;
    125}
    126
    127/* AMP crypto key generation interface */
    128static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
    129{
    130	struct crypto_shash *tfm;
    131	struct shash_desc *shash;
    132	int ret;
    133
    134	if (!ksize)
    135		return -EINVAL;
    136
    137	tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
    138	if (IS_ERR(tfm)) {
    139		BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
    140		return PTR_ERR(tfm);
    141	}
    142
    143	ret = crypto_shash_setkey(tfm, key, ksize);
    144	if (ret) {
    145		BT_DBG("crypto_ahash_setkey failed: err %d", ret);
    146		goto failed;
    147	}
    148
    149	shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
    150			GFP_KERNEL);
    151	if (!shash) {
    152		ret = -ENOMEM;
    153		goto failed;
    154	}
    155
    156	shash->tfm = tfm;
    157
    158	ret = crypto_shash_digest(shash, plaintext, psize, output);
    159
    160	kfree(shash);
    161
    162failed:
    163	crypto_free_shash(tfm);
    164	return ret;
    165}
    166
    167int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
    168{
    169	struct hci_dev *hdev = conn->hdev;
    170	struct link_key *key;
    171	u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
    172	u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
    173	int err;
    174
    175	if (!hci_conn_check_link_mode(conn))
    176		return -EACCES;
    177
    178	BT_DBG("conn %p key_type %d", conn, conn->key_type);
    179
    180	/* Legacy key */
    181	if (conn->key_type < 3) {
    182		bt_dev_err(hdev, "legacy key type %u", conn->key_type);
    183		return -EACCES;
    184	}
    185
    186	*type = conn->key_type;
    187	*len = HCI_AMP_LINK_KEY_SIZE;
    188
    189	key = hci_find_link_key(hdev, &conn->dst);
    190	if (!key) {
    191		BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst);
    192		return -EACCES;
    193	}
    194
    195	/* BR/EDR Link Key concatenated together with itself */
    196	memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
    197	memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
    198
    199	/* Derive Generic AMP Link Key (gamp) */
    200	err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
    201	if (err) {
    202		bt_dev_err(hdev, "could not derive Generic AMP Key: err %d", err);
    203		return err;
    204	}
    205
    206	if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
    207		BT_DBG("Use Generic AMP Key (gamp)");
    208		memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
    209		return err;
    210	}
    211
    212	/* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
    213	return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
    214}
    215
    216static void read_local_amp_assoc_complete(struct hci_dev *hdev, u8 status,
    217					  u16 opcode, struct sk_buff *skb)
    218{
    219	struct hci_rp_read_local_amp_assoc *rp = (void *)skb->data;
    220	struct amp_assoc *assoc = &hdev->loc_assoc;
    221	size_t rem_len, frag_len;
    222
    223	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
    224
    225	if (rp->status)
    226		goto send_rsp;
    227
    228	frag_len = skb->len - sizeof(*rp);
    229	rem_len = __le16_to_cpu(rp->rem_len);
    230
    231	if (rem_len > frag_len) {
    232		BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
    233
    234		memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
    235		assoc->offset += frag_len;
    236
    237		/* Read other fragments */
    238		amp_read_loc_assoc_frag(hdev, rp->phy_handle);
    239
    240		return;
    241	}
    242
    243	memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
    244	assoc->len = assoc->offset + rem_len;
    245	assoc->offset = 0;
    246
    247send_rsp:
    248	/* Send A2MP Rsp when all fragments are received */
    249	a2mp_send_getampassoc_rsp(hdev, rp->status);
    250	a2mp_send_create_phy_link_req(hdev, rp->status);
    251}
    252
    253void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
    254{
    255	struct hci_cp_read_local_amp_assoc cp;
    256	struct amp_assoc *loc_assoc = &hdev->loc_assoc;
    257	struct hci_request req;
    258	int err;
    259
    260	BT_DBG("%s handle %u", hdev->name, phy_handle);
    261
    262	cp.phy_handle = phy_handle;
    263	cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
    264	cp.len_so_far = cpu_to_le16(loc_assoc->offset);
    265
    266	hci_req_init(&req, hdev);
    267	hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
    268	err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
    269	if (err < 0)
    270		a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
    271}
    272
    273void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
    274{
    275	struct hci_cp_read_local_amp_assoc cp;
    276	struct hci_request req;
    277	int err;
    278
    279	memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
    280	memset(&cp, 0, sizeof(cp));
    281
    282	cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
    283
    284	set_bit(READ_LOC_AMP_ASSOC, &mgr->state);
    285	hci_req_init(&req, hdev);
    286	hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
    287	err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
    288	if (err < 0)
    289		a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
    290}
    291
    292void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
    293				   struct hci_conn *hcon)
    294{
    295	struct hci_cp_read_local_amp_assoc cp;
    296	struct amp_mgr *mgr = hcon->amp_mgr;
    297	struct hci_request req;
    298	int err;
    299
    300	if (!mgr)
    301		return;
    302
    303	cp.phy_handle = hcon->handle;
    304	cp.len_so_far = cpu_to_le16(0);
    305	cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
    306
    307	set_bit(READ_LOC_AMP_ASSOC_FINAL, &mgr->state);
    308
    309	/* Read Local AMP Assoc final link information data */
    310	hci_req_init(&req, hdev);
    311	hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
    312	err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
    313	if (err < 0)
    314		a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
    315}
    316
    317static void write_remote_amp_assoc_complete(struct hci_dev *hdev, u8 status,
    318					    u16 opcode, struct sk_buff *skb)
    319{
    320	struct hci_rp_write_remote_amp_assoc *rp = (void *)skb->data;
    321
    322	BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
    323	       hdev->name, rp->status, rp->phy_handle);
    324
    325	if (rp->status)
    326		return;
    327
    328	amp_write_rem_assoc_continue(hdev, rp->phy_handle);
    329}
    330
    331/* Write AMP Assoc data fragments, returns true with last fragment written*/
    332static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
    333				     struct hci_conn *hcon)
    334{
    335	struct hci_cp_write_remote_amp_assoc *cp;
    336	struct amp_mgr *mgr = hcon->amp_mgr;
    337	struct amp_ctrl *ctrl;
    338	struct hci_request req;
    339	u16 frag_len, len;
    340
    341	ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
    342	if (!ctrl)
    343		return false;
    344
    345	if (!ctrl->assoc_rem_len) {
    346		BT_DBG("all fragments are written");
    347		ctrl->assoc_rem_len = ctrl->assoc_len;
    348		ctrl->assoc_len_so_far = 0;
    349
    350		amp_ctrl_put(ctrl);
    351		return true;
    352	}
    353
    354	frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
    355	len = frag_len + sizeof(*cp);
    356
    357	cp = kzalloc(len, GFP_KERNEL);
    358	if (!cp) {
    359		amp_ctrl_put(ctrl);
    360		return false;
    361	}
    362
    363	BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
    364	       hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
    365
    366	cp->phy_handle = hcon->handle;
    367	cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
    368	cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
    369	memcpy(cp->frag, ctrl->assoc, frag_len);
    370
    371	ctrl->assoc_len_so_far += frag_len;
    372	ctrl->assoc_rem_len -= frag_len;
    373
    374	amp_ctrl_put(ctrl);
    375
    376	hci_req_init(&req, hdev);
    377	hci_req_add(&req, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
    378	hci_req_run_skb(&req, write_remote_amp_assoc_complete);
    379
    380	kfree(cp);
    381
    382	return false;
    383}
    384
    385void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
    386{
    387	struct hci_conn *hcon;
    388
    389	BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
    390
    391	hcon = hci_conn_hash_lookup_handle(hdev, handle);
    392	if (!hcon)
    393		return;
    394
    395	/* Send A2MP create phylink rsp when all fragments are written */
    396	if (amp_write_rem_assoc_frag(hdev, hcon))
    397		a2mp_send_create_phy_link_rsp(hdev, 0);
    398}
    399
    400void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
    401{
    402	struct hci_conn *hcon;
    403
    404	BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
    405
    406	hcon = hci_conn_hash_lookup_handle(hdev, handle);
    407	if (!hcon)
    408		return;
    409
    410	BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
    411
    412	amp_write_rem_assoc_frag(hdev, hcon);
    413}
    414
    415static void create_phylink_complete(struct hci_dev *hdev, u8 status,
    416				    u16 opcode)
    417{
    418	struct hci_cp_create_phy_link *cp;
    419
    420	BT_DBG("%s status 0x%2.2x", hdev->name, status);
    421
    422	cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
    423	if (!cp)
    424		return;
    425
    426	hci_dev_lock(hdev);
    427
    428	if (status) {
    429		struct hci_conn *hcon;
    430
    431		hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
    432		if (hcon)
    433			hci_conn_del(hcon);
    434	} else {
    435		amp_write_remote_assoc(hdev, cp->phy_handle);
    436	}
    437
    438	hci_dev_unlock(hdev);
    439}
    440
    441void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
    442			struct hci_conn *hcon)
    443{
    444	struct hci_cp_create_phy_link cp;
    445	struct hci_request req;
    446
    447	cp.phy_handle = hcon->handle;
    448
    449	BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
    450	       hcon->handle);
    451
    452	if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
    453			    &cp.key_type)) {
    454		BT_DBG("Cannot create link key");
    455		return;
    456	}
    457
    458	hci_req_init(&req, hdev);
    459	hci_req_add(&req, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
    460	hci_req_run(&req, create_phylink_complete);
    461}
    462
    463static void accept_phylink_complete(struct hci_dev *hdev, u8 status,
    464				    u16 opcode)
    465{
    466	struct hci_cp_accept_phy_link *cp;
    467
    468	BT_DBG("%s status 0x%2.2x", hdev->name, status);
    469
    470	if (status)
    471		return;
    472
    473	cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
    474	if (!cp)
    475		return;
    476
    477	amp_write_remote_assoc(hdev, cp->phy_handle);
    478}
    479
    480void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
    481			struct hci_conn *hcon)
    482{
    483	struct hci_cp_accept_phy_link cp;
    484	struct hci_request req;
    485
    486	cp.phy_handle = hcon->handle;
    487
    488	BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
    489	       hcon->handle);
    490
    491	if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
    492			    &cp.key_type)) {
    493		BT_DBG("Cannot create link key");
    494		return;
    495	}
    496
    497	hci_req_init(&req, hdev);
    498	hci_req_add(&req, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
    499	hci_req_run(&req, accept_phylink_complete);
    500}
    501
    502void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon)
    503{
    504	struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
    505	struct amp_mgr *mgr = hs_hcon->amp_mgr;
    506	struct l2cap_chan *bredr_chan;
    507
    508	BT_DBG("bredr_hcon %p hs_hcon %p mgr %p", bredr_hcon, hs_hcon, mgr);
    509
    510	if (!bredr_hdev || !mgr || !mgr->bredr_chan)
    511		return;
    512
    513	bredr_chan = mgr->bredr_chan;
    514
    515	l2cap_chan_lock(bredr_chan);
    516
    517	set_bit(FLAG_EFS_ENABLE, &bredr_chan->flags);
    518	bredr_chan->remote_amp_id = hs_hcon->remote_id;
    519	bredr_chan->local_amp_id = hs_hcon->hdev->id;
    520	bredr_chan->hs_hcon = hs_hcon;
    521	bredr_chan->conn->mtu = hs_hcon->hdev->block_mtu;
    522
    523	__l2cap_physical_cfm(bredr_chan, 0);
    524
    525	l2cap_chan_unlock(bredr_chan);
    526
    527	hci_dev_put(bredr_hdev);
    528}
    529
    530void amp_create_logical_link(struct l2cap_chan *chan)
    531{
    532	struct hci_conn *hs_hcon = chan->hs_hcon;
    533	struct hci_cp_create_accept_logical_link cp;
    534	struct hci_dev *hdev;
    535
    536	BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon,
    537	       &chan->conn->hcon->dst);
    538
    539	if (!hs_hcon)
    540		return;
    541
    542	hdev = hci_dev_hold(chan->hs_hcon->hdev);
    543	if (!hdev)
    544		return;
    545
    546	cp.phy_handle = hs_hcon->handle;
    547
    548	cp.tx_flow_spec.id = chan->local_id;
    549	cp.tx_flow_spec.stype = chan->local_stype;
    550	cp.tx_flow_spec.msdu = cpu_to_le16(chan->local_msdu);
    551	cp.tx_flow_spec.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
    552	cp.tx_flow_spec.acc_lat = cpu_to_le32(chan->local_acc_lat);
    553	cp.tx_flow_spec.flush_to = cpu_to_le32(chan->local_flush_to);
    554
    555	cp.rx_flow_spec.id = chan->remote_id;
    556	cp.rx_flow_spec.stype = chan->remote_stype;
    557	cp.rx_flow_spec.msdu = cpu_to_le16(chan->remote_msdu);
    558	cp.rx_flow_spec.sdu_itime = cpu_to_le32(chan->remote_sdu_itime);
    559	cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat);
    560	cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to);
    561
    562	if (hs_hcon->out)
    563		hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp),
    564			     &cp);
    565	else
    566		hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp),
    567			     &cp);
    568
    569	hci_dev_put(hdev);
    570}
    571
    572void amp_disconnect_logical_link(struct hci_chan *hchan)
    573{
    574	struct hci_conn *hcon = hchan->conn;
    575	struct hci_cp_disconn_logical_link cp;
    576
    577	if (hcon->state != BT_CONNECTED) {
    578		BT_DBG("hchan %p not connected", hchan);
    579		return;
    580	}
    581
    582	cp.log_handle = cpu_to_le16(hchan->handle);
    583	hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK, sizeof(cp), &cp);
    584}
    585
    586void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason)
    587{
    588	BT_DBG("hchan %p", hchan);
    589
    590	hci_chan_del(hchan);
    591}