qcacmn: Add support for SET KEY convergence

Make changes to the cmn driver to support SET KEY
convergence feature

Change-Id: I17b5f368a1f735eb394ea70f9b61cc033c3eb20a
CRs-Fixed: 2358796
Цей коміт міститься в:
Kiran Kumar Lokere
2018-09-19 13:48:48 -07:00
зафіксовано nshrivas
джерело ec27e10c2a
коміт 25531c4717
17 змінених файлів з 1014 додано та 40 видалено

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -23,7 +23,6 @@
#define _WLAN_CRYPTO_GLOBAL_API_H_
#include "wlan_crypto_global_def.h"
/**
* wlan_crypto_set_vdev_param - called by ucfg to set crypto param
* @vdev: vdev
@@ -679,4 +678,126 @@ static inline int omac1_aes_256(const uint8_t *key, const uint8_t *data,
}
#endif
/**
* ucfg_crypto_set_key_req() - Set key request to UCFG
* @vdev: vdev object
* @req: key request information
* @pairwise: indicates the type of key to be set, unicast or group key
*
* Return: None
*/
QDF_STATUS ucfg_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *req, bool pairwise);
/**
* wlan_crypto_get_default_key_idx() - Get the default key index
* @vdev: vdev object
* @igtk: denotes if the request is for igtk key type or not
*
* Return: Index of the requested key
*/
int8_t wlan_crypto_get_default_key_idx(struct wlan_objmgr_vdev *vdev,
bool igtk);
/**
* wlan_crypto_get_cipher() - Get the cipher type for the vdev
* @vdev: vdev object
* @pairwise: denotes if the request is for pairwise cipher or not
* @key_index: Index of the key whose cipher type has to be returned
*
* Return: enum wlan_crypto_cipher_type
*/
enum wlan_crypto_cipher_type
wlan_crypto_get_cipher(struct wlan_objmgr_vdev *vdev,
bool pairwise, uint8_t key_index);
#ifdef CRYPTO_SET_KEY_CONVERGED
/**
* wlan_crypto_update_set_key_peer() - Update the peer for set key
* @vdev: vdev object
* @pairwise: denotes if the request is for pairwise cipher or not
* @key_index: Index of the key whose peer has to be set
* @peer_mac: MAC address of the peer
*
* Return: None
*/
void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev,
bool pairwise, uint8_t key_index,
struct qdf_mac_addr *peer_mac);
/**
* wlan_crypto_validate_key_params() - validates key parameters
* @cipher: cipher type
* @key_index: the index of the key
* @key_len: key length
* @seq_len: sequence counter length
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher,
uint8_t key_index, uint8_t key_len,
uint8_t seq_len);
/**
* wlan_crypto_save_key() - Allocate memory for storing key
* @vdev: vdev object
* @key_index: the index of the key that needs to be allocated
* @crypto_key: Pointer to crypto key
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_index,
struct wlan_crypto_key *crypto_key);
/**
* wlan_crypto_get_key() - Get the stored key information
* @vdev: vdev object
* @key_index: the index of the key that needs to be retrieved
*
* Return: Key material
*/
struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_index);
/**
* wlan_crypto_set_key_req() - Set key request
* @vdev: vdev object
* @req: key request information
* @pairwise: indicates the type of key to be set, unicast or group key
*
* Return: QDF status
*/
QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *req, bool pairwise);
#else
static inline void wlan_crypto_update_set_key_peer(
struct wlan_objmgr_vdev *vdev,
bool pairwise,
uint8_t key_index,
struct qdf_mac_addr *peer_mac)
{
}
static inline QDF_STATUS
wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, uint8_t key_index,
struct wlan_crypto_key *crypto_key)
{
return QDF_STATUS_SUCCESS;
}
static inline struct wlan_crypto_key *
wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, uint8_t key_index)
{
return NULL;
}
static inline QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *req,
bool pairwise)
{
return QDF_STATUS_SUCCESS;
}
#endif /* CRYPTO_SET_KEY_CONVERGED */
#endif /* end of _WLAN_CRYPTO_GLOBAL_API_H_ */

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -27,11 +27,14 @@
#ifdef WLAN_CRYPTO_SUPPORT_FILS
#include "wlan_crypto_fils_def.h"
#endif
#include <wlan_objmgr_cmn.h>
#define WLAN_CRYPTO_TID_SIZE (17)
#define WLAN_CRYPTO_RSC_SIZE (16)
#define WLAN_CRYPTO_KEYBUF_SIZE (32)
#define WLAN_CRYPTO_MICBUF_SIZE (16)
#define WLAN_CRYPTO_MIC_LEN (8)
#define WLAN_CRYPTO_IV_SIZE (16)
#define WLAN_CRYPTO_MIC256_LEN (16)
#define WLAN_CRYPTO_TXMIC_OFFSET (0)
#define WLAN_CRYPTO_RXMIC_OFFSET (WLAN_CRYPTO_TXMIC_OFFSET + \
@@ -53,6 +56,14 @@
/* 128 bit wep key len */
#define WLAN_CRYPTO_KEY_WEP128_LEN (16)
#define WLAN_CRYPTO_KEY_TKIP_LEN (32)
#define WLAN_CRYPTO_KEY_CCMP_LEN (16)
#define WLAN_CRYPTO_KEY_CCMP_256_LEN (32)
#define WLAN_CRYPTO_KEY_GCMP_LEN (16)
#define WLAN_CRYPTO_KEY_GCMP_256_LEN (32)
#define WLAN_CRYPTO_KEY_WAPI_LEN (32)
#define WLAN_CRYPTO_KEY_GMAC_LEN (16)
#define WLAN_CRYPTO_KEY_GMAC_256_LEN (32)
#define WLAN_CRYPTO_WPI_SMS4_IVLEN (16)
#define WLAN_CRYPTO_WPI_SMS4_KIDLEN (1)
#define WLAN_CRYPTO_WPI_SMS4_PADLEN (1)
@@ -113,6 +124,7 @@ typedef enum wlan_crypto_cipher_type {
WLAN_CRYPTO_CIPHER_WEP_104 = 16,
WLAN_CRYPTO_CIPHER_NONE = 17,
WLAN_CRYPTO_CIPHER_MAX = WLAN_CRYPTO_CIPHER_NONE,
WLAN_CRYPTO_CIPHER_INVALID,
} wlan_crypto_cipher_type;
/* Auth types */
@@ -188,6 +200,11 @@ typedef enum wlan_crypto_key_mgmt {
WLAN_CRYPTO_KEY_MGMT_MAX = WLAN_CRYPTO_KEY_MGMT_DPP,
} wlan_crypto_key_mgmt;
enum wlan_crypto_key_type {
WLAN_CRYPTO_KEY_TYPE_UNICAST,
WLAN_CRYPTO_KEY_TYPE_GROUP,
};
/**
* struct wlan_crypto_params - holds crypto params
* @authmodeset: authentication mode
@@ -226,6 +243,8 @@ typedef enum wlan_crypto_param_type {
* @valid: is key valid or not
* @flags: key flags
* @keyix: key id
* @cipher_type: cipher type being used for this key
* @mac_addr: MAC address of the peer
* @cipher_table: table which stores cipher related info
* @private: private pointer to save cipher context
* @keylock: spin lock
@@ -245,6 +264,8 @@ struct wlan_crypto_key {
bool valid;
uint16_t flags;
uint16_t keyix;
enum wlan_crypto_cipher_type cipher_type;
uint8_t macaddr[QDF_MAC_ADDR_SIZE];
void *cipher_table;
void *private;
qdf_spinlock_t keylock;
@@ -303,23 +324,26 @@ struct wlan_crypto_req_key {
* @setkey: function pointer to setkey in hw
* @delkey: function pointer to delkey in hw
* @defaultkey: function pointer to set default key
* @set_key: converged function pointer to set key in hw
*/
struct wlan_lmac_if_crypto_tx_ops {
QDF_STATUS(*allockey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS(*setkey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS(*delkey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS(*defaultkey)(struct wlan_objmgr_vdev *vdev,
uint8_t keyix, uint8_t *macaddr);
QDF_STATUS (*allockey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS (*setkey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS (*delkey)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
uint8_t *macaddr, uint32_t key_type);
QDF_STATUS (*defaultkey)(struct wlan_objmgr_vdev *vdev,
uint8_t keyix, uint8_t *macaddr);
QDF_STATUS (*set_key)(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *key,
enum wlan_crypto_key_type key_type);
};
/**
* struct wlan_lmac_if_crypto_rx_ops - structure of crypto rx function
* pointers

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -169,6 +169,8 @@ static inline void wlan_crypto_put_be64(u8 *a, u64 val)
(psoc->soc_cb.tx_ops.crypto_tx_ops.delkey)
#define WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc) \
(psoc->soc_cb.tx_ops.crypto_tx_ops.defaultkey)
#define WLAN_CRYPTO_TX_OPS_SET_KEY(psoc) \
((psoc)->soc_cb.tx_ops.crypto_tx_ops.set_key)
/* unalligned little endian access */
#ifndef LE_READ_2

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -35,10 +35,8 @@
#include "wlan_crypto_def_i.h"
#include "wlan_crypto_param_handling_i.h"
#include "wlan_crypto_obj_mgr_i.h"
#include <qdf_module.h>
const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX];
#define WPA_ADD_CIPHER_TO_SUITE(frm, cipher) \
@@ -954,6 +952,32 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev,
return QDF_STATUS_SUCCESS;
}
#ifdef CRYPTO_SET_KEY_CONVERGED
static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_idx, uint8_t *macaddr)
{
return QDF_STATUS_SUCCESS;
}
#else
static QDF_STATUS wlan_crypto_set_default_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_idx, uint8_t *macaddr)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
crypto_err("psoc is NULL");
return QDF_STATUS_E_INVAL;
}
if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) {
WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx,
macaddr);
}
return QDF_STATUS_SUCCESS;
}
#endif
/**
* wlan_crypto_default_key - called by ucfg to set default tx key
* @vdev: vdev
@@ -1035,10 +1059,9 @@ QDF_STATUS wlan_crypto_default_key(struct wlan_objmgr_vdev *vdev,
if (!key->valid)
return QDF_STATUS_E_INVAL;
if (WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)) {
WLAN_CRYPTO_TX_OPS_DEFAULTKEY(psoc)(vdev, key_idx,
macaddr);
}
if (wlan_crypto_set_default_key(vdev, key_idx, macaddr) !=
QDF_STATUS_SUCCESS)
return QDF_STATUS_E_INVAL;
crypto_priv->def_tx_keyid = key_idx;
return QDF_STATUS_SUCCESS;
@@ -3682,3 +3705,146 @@ QDF_STATUS wlan_set_vdev_crypto_prarams_from_ie(struct wlan_objmgr_vdev *vdev,
return send_fail ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
}
int8_t wlan_crypto_get_default_key_idx(struct wlan_objmgr_vdev *vdev, bool igtk)
{
struct wlan_crypto_comp_priv *crypto_priv;
crypto_priv = wlan_get_vdev_crypto_obj(vdev);
if (!crypto_priv) {
crypto_err("crypto_priv NULL");
return QDF_STATUS_E_FAILURE;
}
if (igtk)
return crypto_priv->def_igtk_tx_keyid;
else
return crypto_priv->def_tx_keyid;
}
enum wlan_crypto_cipher_type
wlan_crypto_get_cipher(struct wlan_objmgr_vdev *vdev,
bool pairwise, uint8_t key_index)
{
struct wlan_crypto_key *crypto_key;
crypto_key = wlan_crypto_get_key(vdev, key_index);
if (crypto_key)
return crypto_key->cipher_type;
else
return WLAN_CRYPTO_CIPHER_INVALID;
}
#ifdef CRYPTO_SET_KEY_CONVERGED
QDF_STATUS wlan_crypto_validate_key_params(enum wlan_crypto_cipher_type cipher,
uint8_t key_index, uint8_t key_len,
uint8_t seq_len)
{
if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
crypto_err("Invalid Key index %d", key_index);
return QDF_STATUS_E_INVAL;
}
if (cipher == WLAN_CRYPTO_CIPHER_INVALID) {
crypto_err("Invalid Cipher %d", cipher);
return QDF_STATUS_E_INVAL;
}
if ((!(cipher == WLAN_CRYPTO_CIPHER_AES_CMAC ||
cipher == WLAN_CRYPTO_CIPHER_AES_CMAC_256 ||
cipher == WLAN_CRYPTO_CIPHER_AES_GMAC ||
cipher == WLAN_CRYPTO_CIPHER_AES_GMAC_256)) &&
(key_index >= WLAN_CRYPTO_MAXKEYIDX)) {
crypto_err("Invalid key index %d for cipher %d",
key_index, cipher);
return QDF_STATUS_E_INVAL;
}
if (key_len > (WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE)) {
crypto_err("Invalid key length %d", key_len);
return QDF_STATUS_E_INVAL;
}
if (seq_len > WLAN_CRYPTO_RSC_SIZE) {
crypto_err("Invalid seq length %d", seq_len);
return QDF_STATUS_E_INVAL;
}
crypto_debug("key: idx:%d, len:%d, seq len:%d",
key_index, key_len, seq_len);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_index,
struct wlan_crypto_key *crypto_key)
{
struct wlan_crypto_comp_priv *crypto_priv;
crypto_priv = wlan_get_vdev_crypto_obj(vdev);
if (!crypto_priv) {
crypto_err("crypto_priv NULL");
return QDF_STATUS_E_FAILURE;
}
if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
crypto_err("Invalid Key index %d", key_index);
return QDF_STATUS_E_FAILURE;
}
if (key_index < WLAN_CRYPTO_MAXKEYIDX)
crypto_priv->key[key_index] = crypto_key;
else
crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] =
crypto_key;
return QDF_STATUS_SUCCESS;
}
struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev,
uint8_t key_index)
{
struct wlan_crypto_comp_priv *crypto_priv;
crypto_priv = wlan_get_vdev_crypto_obj(vdev);
if (!crypto_priv) {
crypto_err("crypto_priv NULL");
return NULL;
}
if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) {
crypto_err("Invalid Key index %d", key_index);
return NULL;
}
if (key_index < WLAN_CRYPTO_MAXKEYIDX)
return crypto_priv->key[key_index];
return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX];
}
QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *req,
bool pairwise)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_vdev_get_psoc(vdev);
if (psoc && WLAN_CRYPTO_TX_OPS_SET_KEY(psoc))
WLAN_CRYPTO_TX_OPS_SET_KEY(psoc)(vdev, req, pairwise);
else
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
}
void wlan_crypto_update_set_key_peer(struct wlan_objmgr_vdev *vdev,
bool pairwise, uint8_t key_index,
struct qdf_mac_addr *peer_mac)
{
struct wlan_crypto_key *crypto_key;
crypto_key = wlan_crypto_get_key(vdev, key_index);
if (!crypto_key) {
crypto_err("crypto_key not present for key_idx %d", key_index);
return;
}
qdf_mem_copy(crypto_key->macaddr, peer_mac, QDF_MAC_ADDR_SIZE);
}
#endif

Переглянути файл

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -40,6 +40,8 @@ cipher2cap(int cipher)
{
switch (cipher) {
case WLAN_CRYPTO_CIPHER_WEP: return WLAN_CRYPTO_CAP_WEP;
case WLAN_CRYPTO_CIPHER_WEP_40: return WLAN_CRYPTO_CAP_WEP;
case WLAN_CRYPTO_CIPHER_WEP_104: return WLAN_CRYPTO_CAP_WEP;
case WLAN_CRYPTO_CIPHER_AES_OCB: return WLAN_CRYPTO_CAP_AES;
case WLAN_CRYPTO_CIPHER_AES_CCM: return WLAN_CRYPTO_CAP_AES;
case WLAN_CRYPTO_CIPHER_AES_CCM_256: return WLAN_CRYPTO_CAP_AES;

Переглянути файл

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* DOC: contains crypto north bound interface definitions
*/
#include <qdf_types.h>
#include <wlan_crypto_global_def.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_crypto_global_api.h>
QDF_STATUS ucfg_crypto_set_key_req(struct wlan_objmgr_vdev *vdev,
struct wlan_crypto_key *req, bool pairwise)
{
/*
* It is the job of dispatcher to decide whether the
* request has to be sent to scheduler or should be
* sent as a offload request or process directly.
*
* Current requirement is to process set key request
* as run to completion without posting any messages.
* Hence the request handler is directly called from
* here.
*/
return wlan_crypto_set_key_req(vdev, req, pairwise);
}