diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h index f293ac0860bb..3121af755364 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -49,6 +49,7 @@ #define WLAN_CRYPTO_KEYIX_NONE ((uint16_t)-1) #define WLAN_CRYPTO_MAXKEYIDX (4) #define WLAN_CRYPTO_MAXIGTKKEYIDX (2) +#define WLAN_CRYPTO_MAXBIGTKKEYIDX (2) #ifndef WLAN_CRYPTO_MAX_VLANKEYIX #define WLAN_CRYPTO_MAX_VLANKEYIX WLAN_CRYPTO_MAXKEYIDX #endif diff --git a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h index e08968bd99ad..79b984c345b4 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_def_i.h +++ b/umac/cmn_services/crypto/src/wlan_crypto_def_i.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -427,9 +427,11 @@ struct wlan_crypto_mmie { * @crypto_params: crypto params for the peer * @key: key buffers for this peer * @igtk_key: igtk key buffer for this peer + * @bigtk_key: bigtk key buffer for this peer * @igtk_key_type: igtk key type * @def_tx_keyid: default key used for this peer * @def_igtk_tx_keyid default igtk key used for this peer + * @def_bigtk_tx_keyid default bigtk key used for this peer * @fils_aead_set fils params for this peer * */ @@ -437,9 +439,11 @@ struct wlan_crypto_comp_priv { struct wlan_crypto_params crypto_params; struct wlan_crypto_key *key[WLAN_CRYPTO_MAX_VLANKEYIX]; struct wlan_crypto_key *igtk_key[WLAN_CRYPTO_MAXIGTKKEYIDX]; + struct wlan_crypto_key *bigtk_key[WLAN_CRYPTO_MAXBIGTKKEYIDX]; uint32_t igtk_key_type; uint8_t def_tx_keyid; uint8_t def_igtk_tx_keyid; + uint8_t def_bigtk_tx_keyid; uint8_t fils_aead_set; }; diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index b917ca0da41e..faf36aca7c48 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -55,6 +55,36 @@ const struct wlan_crypto_cipher *wlan_crypto_cipher_ops[WLAN_CRYPTO_CIPHER_MAX]; WLAN_CRYPTO_ADDSELECTOR(frm,\ wlan_crypto_rsn_keymgmt_to_suite(keymgmt)) +static int is_valid_keyix(uint16_t keyix) +{ + if (keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX + + WLAN_CRYPTO_MAXBIGTKKEYIDX)) + return 0; + else + return 1; +} + +static int is_igtk(uint16_t keyix) +{ + if (keyix < WLAN_CRYPTO_MAXKEYIDX) + return 0; + else if (keyix - WLAN_CRYPTO_MAXKEYIDX >= WLAN_CRYPTO_MAXIGTKKEYIDX) + return 0; + else + return 1; +} + +static int is_bigtk(uint16_t keyix) +{ + if (keyix < (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) + return 0; + if (keyix - WLAN_CRYPTO_MAXKEYIDX - WLAN_CRYPTO_MAXIGTKKEYIDX + >= WLAN_CRYPTO_MAXBIGTKKEYIDX) + return 0; + else + return 1; +} + /** * wlan_crypto_vdev_get_crypto_params - called by mlme to get crypto params * @vdev:vdev @@ -588,6 +618,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, bool isbcast; enum QDF_OPMODE vdev_mode; uint8_t igtk_idx = 0; + uint8_t bigtk_idx = 0; if (!vdev || !req_key || req_key->keylen > (sizeof(req_key->keydata))) { crypto_err("Invalid params vdev%pK, req_key%pK", vdev, req_key); @@ -679,22 +710,40 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, } if (IS_MGMT_CIPHER(req_key->type)) { + struct wlan_crypto_key *crypto_key = NULL; + igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX; - if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) { - crypto_err("igtk key invalid keyid %d", - igtk_idx); + bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX; + if (is_igtk(req_key->keyix)) { + bigtk_idx = 0; + } else if (is_bigtk(req_key->keyix)) { + igtk_idx = 0; + } else { + crypto_err("igtk/bigtk key invalid keyid %d", + req_key->keyix); return QDF_STATUS_E_INVAL; } key = qdf_mem_malloc(sizeof(struct wlan_crypto_key)); if (!key) return QDF_STATUS_E_NOMEM; - if (crypto_priv->igtk_key[igtk_idx]) - qdf_mem_free(crypto_priv->igtk_key[igtk_idx]); - crypto_priv->igtk_key[igtk_idx] = key; - crypto_priv->igtk_key_type = req_key->type; - crypto_priv->def_igtk_tx_keyid = igtk_idx; + if (igtk_idx) { + crypto_key = crypto_priv->igtk_key[igtk_idx]; + if (crypto_key) + qdf_mem_free(crypto_key); + + crypto_priv->igtk_key[igtk_idx] = key; + crypto_priv->igtk_key_type = req_key->type; + crypto_priv->def_igtk_tx_keyid = igtk_idx; + } else { + crypto_key = crypto_priv->bigtk_key[bigtk_idx]; + if (crypto_key) + qdf_mem_free(crypto_key); + + crypto_priv->bigtk_key[bigtk_idx] = key; + crypto_priv->def_bigtk_tx_keyid = bigtk_idx; + } } else { if (IS_FILS_CIPHER(req_key->type)) { crypto_err("FILS key is not for BroadCast pkt"); @@ -720,6 +769,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, crypto_err("peer NULL"); if (IS_MGMT_CIPHER(req_key->type)) { crypto_priv->igtk_key[igtk_idx] = NULL; + crypto_priv->bigtk_key[bigtk_idx] + = NULL; crypto_priv->igtk_key_type = WLAN_CRYPTO_CIPHER_NONE; } else @@ -759,22 +810,39 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_INVAL; } if (IS_MGMT_CIPHER(req_key->type)) { + struct wlan_crypto_key *crypto_key = NULL; + igtk_idx = req_key->keyix - WLAN_CRYPTO_MAXKEYIDX; - if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) { - crypto_err("igtk key invalid keyid %d", - igtk_idx); + bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX; + if (is_igtk(req_key->keyix)) { + bigtk_idx = 0; + } else if (is_bigtk(req_key->keyix)) { + igtk_idx = 0; + } else { + crypto_err("igtk/bigtk key invalid keyid %d", + req_key->keyix); return QDF_STATUS_E_INVAL; } key = qdf_mem_malloc(sizeof(struct wlan_crypto_key)); if (!key) return QDF_STATUS_E_NOMEM; - if (crypto_priv->igtk_key[igtk_idx]) - qdf_mem_free(crypto_priv->igtk_key[igtk_idx]); + if (igtk_idx) { + crypto_key = crypto_priv->igtk_key[igtk_idx]; + if (crypto_key) + qdf_mem_free(crypto_key); - crypto_priv->igtk_key[igtk_idx] = key; - crypto_priv->igtk_key_type = req_key->type; - crypto_priv->def_igtk_tx_keyid = igtk_idx; + crypto_priv->igtk_key[igtk_idx] = key; + crypto_priv->igtk_key_type = req_key->type; + crypto_priv->def_igtk_tx_keyid = igtk_idx; + } else { + crypto_key = crypto_priv->bigtk_key[bigtk_idx]; + if (crypto_key) + qdf_mem_free(crypto_key); + + crypto_priv->bigtk_key[bigtk_idx] = key; + crypto_priv->def_bigtk_tx_keyid = bigtk_idx; + } } else { uint16_t kid = req_key->keyix; if (kid == WLAN_CRYPTO_KEYIX_NONE) @@ -853,7 +921,8 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, key->valid = 1; if ((IS_MGMT_CIPHER(req_key->type))) { if (HAS_CIPHER_CAP(crypto_params, - WLAN_CRYPTO_CAP_PMF_OFFLOAD)) { + WLAN_CRYPTO_CAP_PMF_OFFLOAD) || + is_bigtk(req_key->keyix)) { if (WLAN_CRYPTO_TX_OPS_SETKEY(psoc)) { WLAN_CRYPTO_TX_OPS_SETKEY(psoc)(vdev, key, macaddr, req_key->type); @@ -928,10 +997,13 @@ struct wlan_crypto_key *wlan_crypto_vdev_getkey(struct wlan_objmgr_vdev *vdev, * we return the default key, for all other keyix we return the * key accordingly. */ - if (keyix == WLAN_CRYPTO_KEYIX_NONE || - keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) + if ((keyix == WLAN_CRYPTO_KEYIX_NONE) || + !is_valid_keyix(keyix)) key = crypto_priv->key[crypto_priv->def_tx_keyid]; - else if (keyix >= WLAN_CRYPTO_MAXKEYIDX) + else if (is_bigtk(keyix)) + key = crypto_priv->bigtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX + - WLAN_CRYPTO_MAXIGTKKEYIDX]; + else if (is_igtk(keyix)) key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX]; else key = crypto_priv->key[keyix]; @@ -970,9 +1042,12 @@ struct wlan_crypto_key *wlan_crypto_peer_getkey(struct wlan_objmgr_peer *peer, * key accordingly. */ if (keyix == WLAN_CRYPTO_KEYIX_NONE || - keyix >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) + !is_valid_keyix(keyix)) key = crypto_priv->key[crypto_priv->def_tx_keyid]; - else if (keyix >= WLAN_CRYPTO_MAXKEYIDX) + else if (is_bigtk(keyix)) + key = crypto_priv->bigtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX + - WLAN_CRYPTO_MAXIGTKKEYIDX]; + else if (is_igtk(keyix)) key = crypto_priv->igtk_key[keyix - WLAN_CRYPTO_MAXKEYIDX]; else key = crypto_priv->key[keyix]; @@ -1097,8 +1172,7 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, uint8_t bssid_mac[QDF_MAC_ADDR_SIZE]; if (!vdev || !macaddr || - (key_idx >= - (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX))) { + !is_valid_keyix(key_idx)) { crypto_err("Invalid param vdev %pK macaddr %pK keyidx %d", vdev, macaddr, key_idx); return QDF_STATUS_E_INVAL; @@ -1147,12 +1221,23 @@ QDF_STATUS wlan_crypto_delkey(struct wlan_objmgr_vdev *vdev, if (key_idx >= WLAN_CRYPTO_MAXKEYIDX) { uint8_t igtk_idx = key_idx - WLAN_CRYPTO_MAXKEYIDX; - if (igtk_idx >= WLAN_CRYPTO_MAXIGTKKEYIDX) { - crypto_err("Igtk key invalid keyid %d", igtk_idx); + uint8_t bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX; + + if (is_igtk(key_idx)) { + bigtk_idx = 0; + } else if (is_bigtk(key_idx)) { + igtk_idx = 0; + } else { + crypto_err("igtk/bigtk key invalid keyid %d", key_idx); return QDF_STATUS_E_INVAL; } - key = crypto_priv->igtk_key[igtk_idx]; - crypto_priv->igtk_key[igtk_idx] = NULL; + if (igtk_idx) { + key = crypto_priv->igtk_key[igtk_idx]; + crypto_priv->igtk_key[igtk_idx] = NULL; + } else { + key = crypto_priv->bigtk_key[bigtk_idx]; + crypto_priv->bigtk_key[bigtk_idx] = NULL; + } if (key) key->valid = 0; } else { @@ -4114,7 +4199,7 @@ 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)) { + if (!is_valid_keyix(key_index)) { crypto_err("Invalid Key index %d", key_index); return QDF_STATUS_E_INVAL; } @@ -4158,15 +4243,18 @@ QDF_STATUS wlan_crypto_save_key(struct wlan_objmgr_vdev *vdev, crypto_err("crypto_priv NULL"); return QDF_STATUS_E_FAILURE; } - if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + if (!is_valid_keyix(key_index)) { 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 + else if (is_igtk(key_index)) crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX] = crypto_key; + else + crypto_priv->bigtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX + - WLAN_CRYPTO_MAXIGTKKEYIDX] = crypto_key; return QDF_STATUS_SUCCESS; } @@ -4181,14 +4269,19 @@ struct wlan_crypto_key *wlan_crypto_get_key(struct wlan_objmgr_vdev *vdev, crypto_err("crypto_priv NULL"); return NULL; } - if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX)) { + if (!is_valid_keyix(key_index)) { crypto_err("Invalid Key index %d", key_index); return NULL; } if (key_index < WLAN_CRYPTO_MAXKEYIDX) return crypto_priv->key[key_index]; + else if (is_igtk(key_index)) + return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX]; + else + return crypto_priv->bigtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX + - WLAN_CRYPTO_MAXIGTKKEYIDX]; - return crypto_priv->igtk_key[key_index - WLAN_CRYPTO_MAXKEYIDX]; + return NULL; } QDF_STATUS wlan_crypto_set_key_req(struct wlan_objmgr_vdev *vdev, diff --git a/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c b/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c index 401ca5c7d09b..0e3e52848df4 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_obj_mgr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -195,6 +195,13 @@ static void wlan_crypto_free_key(struct wlan_crypto_comp_priv *crypto_priv) } } + for (i = 0; i < WLAN_CRYPTO_MAXBIGTKKEYIDX; i++) { + if (crypto_priv->bigtk_key[i]) { + qdf_mem_free(crypto_priv->bigtk_key[i]); + crypto_priv->bigtk_key[i] = NULL; + } + } + } static QDF_STATUS wlan_crypto_vdev_obj_destroy_handler( diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h index a8c532a963f7..464ae7c884d5 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h @@ -89,6 +89,9 @@ #define WLAN_PDEV_F_MBSS_IE_ENABLE 0x20000000 /* VDEV Peer delete all */ #define WLAN_PDEV_F_DELETE_ALL_PEER 0x40000000 +/* PDEV BEacon Protection */ +#define WLAN_PDEV_F_BEACON_PROTECTION 0x80000000 + /* PDEV op flags */ /* Enable htrate for wep and tkip */ diff --git a/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h b/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h index f80d1514e804..daa5d30d2213 100644 --- a/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h +++ b/umac/mlme/vdev_mgr/dispatcher/inc/wlan_vdev_mgr_tgt_if_tx_defs.h @@ -171,6 +171,7 @@ struct tbttoffset_params { * @ext_csa_switch_count_offset: ECSA switch count offset in beacon frame * @esp_ie_offset: ESP IE offset in beacon frame * @mu_edca_ie_offset: Mu EDCA IE offset in beacon frame + * @enable_bigtk: enable bigtk or not * @frm: beacon template parameter */ struct beacon_tmpl_params { @@ -183,6 +184,7 @@ struct beacon_tmpl_params { uint32_t ext_csa_switch_count_offset; uint32_t esp_ie_offset; uint32_t mu_edca_ie_offset; + bool enable_bigtk; uint8_t *frm; }; diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 096eab63fd9c..985d9697bd51 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -5120,6 +5120,7 @@ typedef enum { wmi_service_time_sync_ftm, wmi_service_nss_ratio_to_host_support, wmi_roam_scan_chan_list_to_host_support, + wmi_beacon_protection_support, wmi_services_max, } wmi_conv_service_ids; #define WMI_SERVICE_UNAVAILABLE 0xFFFF diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 57a875f7c9f8..651e27988856 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -2402,6 +2402,9 @@ static QDF_STATUS send_beacon_tmpl_send_cmd_tlv(wmi_unified_t wmi_handle, cmd->esp_ie_offset = param->esp_ie_offset; cmd->mu_edca_ie_offset = param->mu_edca_ie_offset; cmd->buf_len = param->tmpl_len; + + WMI_BEACON_PROTECTION_EN_SET(cmd->feature_enable_bitmap, + param->enable_bigtk); buf_ptr += sizeof(wmi_bcn_tmpl_cmd_fixed_param); bcn_prb_info = (wmi_bcn_prb_info *) buf_ptr; @@ -14436,6 +14439,8 @@ static void populate_tlv_service(uint32_t *wmi_service) WMI_SERVICE_NSS_RATIO_TO_HOST_SUPPORT; wmi_service[wmi_roam_scan_chan_list_to_host_support] = WMI_SERVICE_ROAM_SCAN_CHANNEL_LIST_TO_HOST_SUPPORT; + wmi_service[wmi_beacon_protection_support] = + WMI_SERVICE_BEACON_PROTECTION_SUPPORT; } /**