mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-24 21:54:34 -04:00
qcacmn: [CRYPTO] Fix encap/decap issues in TKIP/WEP
1. Fetch keyid from pkt during TKIP demic 2. Support to restore keys in h/w keycache, when h/w reset takes place Change-Id: Icc4039a6cf6b89bd3ec3a874b698445382aff024 CRs-Fixed: 2233228
This commit is contained in:
parent
51d1103376
commit
43ebaa7182
5 changed files with 172 additions and 14 deletions
|
|
@ -200,15 +200,17 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
|
|||
* @wbuf: wbuf
|
||||
* @macaddr: macaddr
|
||||
* @tid: tid of the frame
|
||||
* @keyid: keyid in the received frame
|
||||
*
|
||||
* This function gets called from mgmt txrx to decap frame.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_nbuf_t wbuf,
|
||||
uint8_t *macaddr,
|
||||
uint8_t tid);
|
||||
qdf_nbuf_t wbuf,
|
||||
uint8_t *macaddr,
|
||||
uint8_t tid,
|
||||
uint8_t keyid);
|
||||
|
||||
/**
|
||||
* wlan_crypto_vdev_is_pmf_enabled - called to check is pmf enabled in vdev
|
||||
|
|
@ -576,4 +578,14 @@ uint8_t wlan_crypto_get_key_miclen(struct wlan_crypto_key *key);
|
|||
* Return: keyid
|
||||
*/
|
||||
uint16_t wlan_crypto_get_keyid(uint8_t *data, int hdrlen);
|
||||
|
||||
/**
|
||||
* wlan_crypto_restore_keys - restore crypto keys in hw keycache
|
||||
* @vdev: vdev
|
||||
*
|
||||
* This function restores keys in hw keycache
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void wlan_crypto_restore_keys(struct wlan_objmgr_vdev *vdev);
|
||||
#endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ struct wlan_lmac_if_crypto_rx_ops {
|
|||
uint8_t encapdone);
|
||||
QDF_STATUS(*crypto_demic)(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_nbuf_t wbuf, uint8_t *macaddr,
|
||||
uint8_t tid);
|
||||
uint8_t tid, uint8_t keyid);
|
||||
QDF_STATUS(*set_peer_wep_keys)(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_objmgr_peer *peer);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -649,6 +649,16 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev,
|
|||
}
|
||||
status = cipher->setkey(key);
|
||||
|
||||
if ((req_key->flags & WLAN_CRYPTO_KEY_DEFAULT) &&
|
||||
(req_key->keyix != WLAN_CRYPTO_KEYIX_NONE) &&
|
||||
(!IS_MGMT_CIPHER(req_key->type))) {
|
||||
/* default xmit key */
|
||||
wlan_crypto_default_key(vdev,
|
||||
req_key->macaddr,
|
||||
req_key->keyix,
|
||||
!isbcast);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1346,15 +1356,16 @@ QDF_STATUS wlan_crypto_enmic(struct wlan_objmgr_vdev *vdev,
|
|||
* @wbuf: wbuf
|
||||
* @macaddr: macaddr
|
||||
* @tid: tid of the frame
|
||||
*
|
||||
* @keyid: keyid in the received frame
|
||||
* This function gets called from mgmt txrx to decap frame.
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS - in case of success
|
||||
*/
|
||||
QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_nbuf_t wbuf,
|
||||
uint8_t *mac_addr,
|
||||
uint8_t tid){
|
||||
qdf_nbuf_t wbuf,
|
||||
uint8_t *mac_addr,
|
||||
uint8_t tid,
|
||||
uint8_t keyid){
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
struct wlan_crypto_params *crypto_params;
|
||||
struct wlan_crypto_key *key;
|
||||
|
|
@ -1392,7 +1403,7 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
|
|||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
key = crypto_priv->key[crypto_priv->def_tx_keyid];
|
||||
key = crypto_priv->key[keyid];
|
||||
if (!key)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
|
|
@ -1420,7 +1431,7 @@ QDF_STATUS wlan_crypto_demic(struct wlan_objmgr_vdev *vdev,
|
|||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
key = crypto_priv->key[crypto_priv->def_tx_keyid];
|
||||
key = crypto_priv->key[keyid];
|
||||
if (!key)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
|
@ -3201,3 +3212,127 @@ uint16_t wlan_crypto_get_keyid(uint8_t *data, int hdrlen)
|
|||
}
|
||||
|
||||
qdf_export_symbol(wlan_crypto_get_keyid);
|
||||
|
||||
/**
|
||||
* crypto_plumb_peer_keys - called during radio reset
|
||||
* @vdev: vdev
|
||||
* @object: peer
|
||||
* @arg: psoc
|
||||
*
|
||||
* Restore unicast and persta hardware keys
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void crypto_plumb_peer_keys(struct wlan_objmgr_vdev *vdev,
|
||||
void *object, void *arg) {
|
||||
struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)object;
|
||||
struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)arg;
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
struct wlan_crypto_params *crypto_params;
|
||||
struct wlan_crypto_key *key = NULL;
|
||||
int i;
|
||||
|
||||
if ((NULL == peer) || (NULL == vdev) || (NULL == psoc)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s[%d] Peer or vdev or psoc objects are null!\n",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_params = wlan_crypto_peer_get_comp_params(peer,
|
||||
&crypto_priv);
|
||||
|
||||
if (!crypto_priv) {
|
||||
QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s[%d] crypto_priv NULL\n",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
|
||||
key = crypto_priv->key[i];
|
||||
if (key && key->valid) {
|
||||
if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
|
||||
WLAN_CRYPTO_TX_OPS_SETKEY(psoc)
|
||||
(
|
||||
vdev,
|
||||
key,
|
||||
wlan_peer_get_macaddr(peer),
|
||||
wlan_crypto_get_key_type(key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_crypto_restore_keys - called during radio reset
|
||||
* @vdev: vdev
|
||||
*
|
||||
* Clear and restore keycache, needed for some DA chipsets which put
|
||||
* random values in keycache when phy reset is triggered
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void wlan_crypto_restore_keys(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
int i;
|
||||
struct wlan_crypto_comp_priv *crypto_priv;
|
||||
struct wlan_crypto_params *crypto_params;
|
||||
struct wlan_crypto_key *key;
|
||||
uint8_t macaddr[WLAN_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
struct wlan_objmgr_pdev *pdev = NULL;
|
||||
struct wlan_objmgr_psoc *psoc = NULL;
|
||||
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (NULL == pdev) {
|
||||
QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s[%d] pdev is NULL\n",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
if (NULL == psoc) {
|
||||
QDF_TRACE(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s[%d] psoc is NULL\n",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TBD: QWRAP key restore*/
|
||||
/* crypto is on */
|
||||
if (wlan_vdev_mlme_feat_cap_get(vdev, WLAN_VDEV_F_PRIVACY)) {
|
||||
/* restore static shared keys */
|
||||
for (i = 0; i < WLAN_CRYPTO_MAXKEYIDX; i++) {
|
||||
crypto_params = wlan_crypto_vdev_get_comp_params
|
||||
(
|
||||
vdev,
|
||||
&crypto_priv
|
||||
);
|
||||
if (!crypto_priv) {
|
||||
QDF_TRACE(QDF_MODULE_ID_CRYPTO,
|
||||
QDF_TRACE_LEVEL_ERROR,
|
||||
"%s[%d] crypto_priv is NULL\n",
|
||||
__func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
key = crypto_priv->key[i];
|
||||
if (key && key->valid) {
|
||||
if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) {
|
||||
WLAN_CRYPTO_TX_OPS_SETKEY(psoc)
|
||||
(
|
||||
vdev,
|
||||
key,
|
||||
macaddr,
|
||||
wlan_crypto_get_key_type(key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wlan_objmgr_iterate_peerobj_list(vdev,
|
||||
crypto_plumb_peer_keys,
|
||||
psoc,
|
||||
WLAN_CRYPTO_ID);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,10 +60,17 @@ static QDF_STATUS tkip_encap(struct wlan_crypto_key *key,
|
|||
if (encapdone) {
|
||||
ivp = (uint8_t *)qdf_nbuf_data(wbuf);
|
||||
} else {
|
||||
ivp = qdf_nbuf_push_head(wbuf, cipher_table->header);
|
||||
qdf_mem_move(ivp, (ivp + cipher_table->header), hdrlen);
|
||||
uint8_t ivmictrailer_len = cipher_table->header +
|
||||
cipher_table->miclen +
|
||||
cipher_table->trailer;
|
||||
ivp = qdf_nbuf_push_head(wbuf, ivmictrailer_len);
|
||||
qdf_mem_move(ivp, (ivp + ivmictrailer_len), hdrlen);
|
||||
qdf_mem_move((ivp + hdrlen + cipher_table->header),
|
||||
(ivp + ivmictrailer_len + hdrlen),
|
||||
(qdf_nbuf_len(wbuf) - hdrlen - ivmictrailer_len));
|
||||
}
|
||||
|
||||
ivp += hdrlen;
|
||||
key->keytsc++; /* XXX wrap at 48 bits */
|
||||
|
||||
ivp[0] = key->keytsc >> 8; /* TSC1 */
|
||||
|
|
@ -151,13 +158,17 @@ static QDF_STATUS tkip_demic(struct wlan_crypto_key *key,
|
|||
qdf_nbuf_t wbuf,
|
||||
uint8_t tid,
|
||||
uint8_t hdrlen){
|
||||
struct wlan_crypto_cipher *cipher_table;
|
||||
|
||||
cipher_table = key->cipher_table;
|
||||
qdf_nbuf_trim_tail(wbuf, cipher_table->miclen);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const struct wlan_crypto_cipher tkip_cipher_table = {
|
||||
"TKIP",
|
||||
WLAN_CRYPTO_CIPHER_TKIP,
|
||||
WLAN_CRYPTO_IV_LEN + WLAN_CRYPTO_KEYID_LEN,
|
||||
WLAN_CRYPTO_IV_LEN + WLAN_CRYPTO_KEYID_LEN + WLAN_CRYPTO_EXT_IV_LEN,
|
||||
WLAN_CRYPTO_CRC_LEN,
|
||||
WLAN_CRYPTO_MIC_LEN,
|
||||
256,
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static QDF_STATUS wep_encap(struct wlan_crypto_key *key,
|
|||
ivp + hdrlen
|
||||
+ cipher_table->header + cipher_table->trailer,
|
||||
(qdf_nbuf_len(wbuf) - hdrlen
|
||||
- cipher_table->header + cipher_table->trailer));
|
||||
- cipher_table->header - cipher_table->trailer));
|
||||
ivp = (uint8_t *)qdf_nbuf_data(wbuf);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue