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(uint8_t key_index, bool pairwise, 32 const u8 *mac_addr, 33 struct key_params *params, 34 struct wlan_crypto_key *crypto_key) 35 { 36 static const struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT; 37 38 qdf_mem_zero(crypto_key, sizeof(*crypto_key)); 39 crypto_key->keylen = params->key_len; 40 crypto_key->keyix = key_index; 41 qdf_mem_copy(&crypto_key->keyval[0], params->key, params->key_len); 42 qdf_mem_copy(&crypto_key->keyrsc[0], params->seq, params->seq_len); 43 44 crypto_key->cipher_type = osif_nl_to_crypto_cipher_type(params->cipher); 45 if (pairwise) { 46 crypto_key->flags |= PAIRWISE_USAGE; 47 qdf_mem_copy(&crypto_key->macaddr, mac_addr, 48 QDF_MAC_ADDR_SIZE); 49 } else { 50 crypto_key->flags |= GROUP_USAGE; 51 qdf_mem_copy(&crypto_key->macaddr, &bcast_mac, 52 QDF_MAC_ADDR_SIZE); 53 } 54 } 55 56 int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev, 57 uint8_t key_index, bool pairwise, 58 const u8 *mac_addr, struct key_params *params) 59 { 60 struct wlan_crypto_key *crypto_key = NULL; 61 enum wlan_crypto_cipher_type cipher; 62 int cipher_len; 63 QDF_STATUS status; 64 65 if (!vdev) { 66 cfg80211_err("vdev is NULL"); 67 return -EINVAL; 68 } 69 if (!params) { 70 cfg80211_err("Key params is NULL"); 71 return -EINVAL; 72 } 73 if (pairwise && !mac_addr) { 74 cfg80211_err("mac_addr is NULL for pairwise Key"); 75 return -EINVAL; 76 } 77 cipher_len = osif_nl_to_crypto_cipher_len(params->cipher); 78 if (cipher_len < 0 || params->key_len < cipher_len) { 79 cfg80211_err("cipher length %d less than reqd len %d", 80 params->key_len, cipher_len); 81 return -EINVAL; 82 } 83 cipher = osif_nl_to_crypto_cipher_type(params->cipher); 84 status = wlan_crypto_validate_key_params(cipher, key_index, 85 params->key_len, 86 params->seq_len); 87 if (QDF_IS_STATUS_ERROR(status)) { 88 cfg80211_err("Invalid key params"); 89 return -EINVAL; 90 } 91 92 /* 93 * key may already exist at times and may be retrieved only to 94 * update it. 95 */ 96 crypto_key = wlan_crypto_get_key(vdev, key_index); 97 if (!crypto_key) { 98 crypto_key = qdf_mem_malloc(sizeof(*crypto_key)); 99 if (!crypto_key) 100 return -EINVAL; 101 status = wlan_crypto_save_key(vdev, key_index, crypto_key); 102 if (QDF_IS_STATUS_ERROR(status)) { 103 cfg80211_err("Failed to save key"); 104 qdf_mem_free(crypto_key); 105 return -EINVAL; 106 } 107 } 108 109 wlan_cfg80211_translate_key(key_index, pairwise, mac_addr, 110 params, crypto_key); 111 112 return 0; 113 } 114 115 int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev, bool pairwise, 116 uint8_t key_index) 117 { 118 struct wlan_crypto_key *crypto_key; 119 QDF_STATUS status; 120 121 crypto_key = wlan_crypto_get_key(vdev, key_index); 122 if (!crypto_key) { 123 cfg80211_err("Crypto KEY is NULL"); 124 return -EINVAL; 125 } 126 status = ucfg_crypto_set_key_req(vdev, crypto_key, pairwise); 127 128 return qdf_status_to_os_return(status); 129 } 130 131 #ifdef CONFIG_CRYPTO_COMPONENT 132 int wlan_cfg80211_set_default_key(struct wlan_objmgr_vdev *vdev, 133 uint8_t key_index, struct qdf_mac_addr *bssid) 134 { 135 return wlan_crypto_default_key(vdev, (uint8_t *)bssid, 136 key_index, true); 137 } 138 #endif 139