1 /* 2 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: defines crypto driver functions interfacing with linux kernel 21 */ 22 #include <wlan_crypto_global_def.h> 23 #include <wlan_crypto_global_api.h> 24 #include <wlan_objmgr_vdev_obj.h> 25 #include <wlan_crypto_main_i.h> 26 #include <net/cfg80211.h> 27 #include <wlan_nl_to_crypto_params.h> 28 #include "wlan_cfg80211_crypto.h" 29 #include <wlan_cfg80211.h> 30 31 static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev, 32 uint8_t key_index, 33 enum wlan_crypto_key_type key_type, 34 const u8 *mac_addr, 35 struct key_params *params, 36 struct wlan_crypto_key *crypto_key) 37 { 38 qdf_mem_zero(crypto_key, sizeof(*crypto_key)); 39 crypto_key->keylen = params->key_len; 40 crypto_key->keyix = key_index; 41 osif_debug("key_type %d, opmode %d, key_len %d, seq_len %d", 42 key_type, vdev->vdev_mlme.vdev_opmode, 43 params->key_len, params->seq_len); 44 qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); 45 qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); 46 47 crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(params->cipher); 48 if (IS_WEP_CIPHER(crypto_key->cipher_type) && !mac_addr) { 49 /* 50 * This is a valid scenario in case of WEP, where-in the 51 * keys are passed by the user space during the connect request 52 * but since we did not connect yet, so we do not know the peer 53 * address yet. 54 */ 55 osif_debug("No Mac Address to copy"); 56 return; 57 } 58 if (key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) { 59 qdf_mem_copy(&crypto_key->macaddr, mac_addr, QDF_MAC_ADDR_SIZE); 60 } else { 61 if ((vdev->vdev_mlme.vdev_opmode == QDF_STA_MODE) || 62 (vdev->vdev_mlme.vdev_opmode == QDF_P2P_CLIENT_MODE)) 63 qdf_mem_copy(&crypto_key->macaddr, mac_addr, 64 QDF_MAC_ADDR_SIZE); 65 else 66 qdf_mem_copy(&crypto_key->macaddr, 67 vdev->vdev_mlme.macaddr, 68 QDF_MAC_ADDR_SIZE); 69 } 70 osif_debug("mac "QDF_MAC_ADDR_FMT, 71 QDF_MAC_ADDR_REF(crypto_key->macaddr)); 72 } 73 74 int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, 75 uint8_t key_index, 76 enum wlan_crypto_key_type key_type, 77 const u8 *mac_addr, struct key_params *params) 78 { 79 struct wlan_crypto_key *crypto_key = NULL; 80 enum wlan_crypto_cipher_type cipher; 81 int cipher_len; 82 QDF_STATUS status; 83 84 if (!vdev) { 85 osif_err("vdev is NULL"); 86 return -EINVAL; 87 } 88 if (!params) { 89 osif_err("Key params is NULL"); 90 return -EINVAL; 91 } 92 cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); 93 if (cipher_len < 0 || params->key_len < cipher_len) { 94 osif_err("cipher length %d less than reqd len %d", 95 params->key_len, cipher_len); 96 return -EINVAL; 97 } 98 cipher = osif_nl_to_crypto_cipher_type(params->cipher); 99 if (!IS_WEP_CIPHER(cipher)) { 100 if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && 101 !mac_addr) { 102 osif_err("mac_addr is NULL for pairwise Key"); 103 return -EINVAL; 104 } 105 } 106 status = wlan_crypto_validate_key_params(cipher, key_index, 107 params->key_len, 108 params->seq_len); 109 if (QDF_IS_STATUS_ERROR(status)) { 110 osif_err("Invalid key params"); 111 return -EINVAL; 112 } 113 114 /* 115 * key may already exist at times and may be retrieved only to 116 * update it. 117 */ 118 crypto_key = wlan_crypto_get_key(vdev, key_index); 119 if (!crypto_key) { 120 crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); 121 if (!crypto_key) 122 return -EINVAL; 123 } 124 125 wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr, 126 params, crypto_key); 127 128 status = wlan_crypto_save_key(vdev, key_index, crypto_key); 129 if (QDF_IS_STATUS_ERROR(status)) { 130 osif_err("Failed to save key"); 131 qdf_mem_free(crypto_key); 132 return -EINVAL; 133 } 134 return 0; 135 } 136 137 int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, 138 enum wlan_crypto_key_type key_type, 139 uint8_t key_index) 140 { 141 struct wlan_crypto_key *crypto_key; 142 QDF_STATUS status; 143 144 crypto_key = wlan_crypto_get_key(vdev, key_index); 145 if (!crypto_key) { 146 osif_err("Crypto KEY is NULL"); 147 return -EINVAL; 148 } 149 status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); 150 151 return qdf_status_to_os_return(status); 152 } 153 154 #ifdef WLAN_CONV_CRYPTO_SUPPORTED 155 int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, 156 uint8_t key_index, struct qdf_mac_addr *bssid) 157 { 158 return wlan_crypto_default_key(vdev, (uint8_t *)bssid, 159 key_index, true); 160 } 161 #endif 162