xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/crypto/src/wlan_cfg80211_crypto.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
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