1 /* 2 * Copyright (c) 2019 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 cfg80211_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 cfg80211_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 cfg80211_debug("mac %pM", crypto_key->macaddr); 71 } 72 73 int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, 74 uint8_t key_index, 75 enum wlan_crypto_key_type key_type, 76 const u8 *mac_addr, struct key_params *params) 77 { 78 struct wlan_crypto_key *crypto_key = NULL; 79 enum wlan_crypto_cipher_type cipher; 80 int cipher_len; 81 QDF_STATUS status; 82 83 if (!vdev) { 84 cfg80211_err("vdev is NULL"); 85 return -EINVAL; 86 } 87 if (!params) { 88 cfg80211_err("Key params is NULL"); 89 return -EINVAL; 90 } 91 cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); 92 if (cipher_len < 0 || params->key_len < cipher_len) { 93 cfg80211_err("cipher length %d less than reqd len %d", 94 params->key_len, cipher_len); 95 return -EINVAL; 96 } 97 cipher = osif_nl_to_crypto_cipher_type(params->cipher); 98 if (!IS_WEP_CIPHER(cipher)) { 99 if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && 100 !mac_addr) { 101 cfg80211_err("mac_addr is NULL for pairwise Key"); 102 return -EINVAL; 103 } 104 } 105 status = wlan_crypto_validate_key_params(cipher, key_index, 106 params->key_len, 107 params->seq_len); 108 if (QDF_IS_STATUS_ERROR(status)) { 109 cfg80211_err("Invalid key params"); 110 return -EINVAL; 111 } 112 113 /* 114 * key may already exist at times and may be retrieved only to 115 * update it. 116 */ 117 crypto_key = wlan_crypto_get_key(vdev, key_index); 118 if (!crypto_key) { 119 crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); 120 if (!crypto_key) 121 return -EINVAL; 122 status = wlan_crypto_save_key(vdev, key_index, crypto_key); 123 if (QDF_IS_STATUS_ERROR(status)) { 124 cfg80211_err("Failed to save key"); 125 qdf_mem_free(crypto_key); 126 return -EINVAL; 127 } 128 } 129 130 wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr, 131 params, crypto_key); 132 133 return 0; 134 } 135 136 int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, 137 enum wlan_crypto_key_type key_type, 138 uint8_t key_index) 139 { 140 struct wlan_crypto_key *crypto_key; 141 QDF_STATUS status; 142 143 crypto_key = wlan_crypto_get_key(vdev, key_index); 144 if (!crypto_key) { 145 cfg80211_err("Crypto KEY is NULL"); 146 return -EINVAL; 147 } 148 status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type); 149 150 return qdf_status_to_os_return(status); 151 } 152 153 #ifdef CONFIG_CRYPTO_COMPONENT 154 int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, 155 uint8_t key_index, struct qdf_mac_addr *bssid) 156 { 157 return wlan_crypto_default_key(vdev, (uint8_t *)bssid, 158 key_index, true); 159 } 160 #endif 161