xref: /wlan-dirver/qca-wifi-host-cmn/target_if/crypto/src/target_if_crypto.c (revision 8ddef7dd9a290d4a9b1efd5d3efacf51d78a1a0d)
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: offload lmac interface APIs definitions for crypto
21  */
22 
23 #include <qdf_mem.h>
24 #include <qdf_status.h>
25 #include <target_if_crypto.h>
26 #include <wmi_unified_priv.h>
27 #include <wmi_unified_param.h>
28 #include <wlan_objmgr_psoc_obj.h>
29 #include <target_if.h>
30 #include <wlan_crypto_global_def.h>
31 #include <wlan_crypto_global_api.h>
32 #include <wlan_objmgr_vdev_obj.h>
33 #include <cdp_txrx_cmn_struct.h>
34 #include <cds_api.h>
35 #include <cdp_txrx_cmn.h>
36 #include <wmi_unified_api.h>
37 #include <cdp_txrx_peer_ops.h>
38 
39 #ifdef FEATURE_WLAN_WAPI
40 static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
41 				     bool pairwise,
42 				     enum wlan_crypto_cipher_type cipher_type,
43 				     struct set_key_params *params)
44 {
45 	static const unsigned char tx_iv[16] = {0x36, 0x5c, 0x36, 0x5c, 0x36,
46 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
47 						0x36, 0x5c, 0x36, 0x5c, 0x36,
48 						0x5c};
49 
50 	static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
51 						0x36, 0x5c, 0x36, 0x5c, 0x36,
52 						0x5c, 0x36, 0x5c, 0x36, 0x5c,
53 						0x37};
54 
55 	if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 ||
56 	    cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4)
57 		return;
58 
59 	qdf_mem_copy(&params->rx_iv, &rx_iv,
60 		     WLAN_CRYPTO_WAPI_IV_SIZE);
61 	qdf_mem_copy(&params->tx_iv, &tx_iv,
62 		     WLAN_CRYPTO_WAPI_IV_SIZE);
63 
64 	if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) {
65 		if (pairwise)
66 			params->tx_iv[0] = 0x37;
67 
68 		params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
69 	} else {
70 		if (!pairwise)
71 			params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
72 	}
73 
74 	params->key_txmic_len = WLAN_CRYPTO_MIC_LEN;
75 	params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
76 }
77 #else
78 static inline void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
79 					    bool pairwise,
80 					    enum wlan_crypto_cipher_type cipher,
81 					    struct set_key_params *params)
82 {
83 }
84 #endif /* FEATURE_WLAN_WAPI */
85 
86 #ifdef BIG_ENDIAN_HOST
87 static void wlan_crypto_endianness_conversion(uint8_t *dest, uint8_t *src,
88 					      uint32_t keylen)
89 {
90 	int8_t i;
91 
92 	for (i = 0; i < roundup(keylen, sizeof(uint32_t)) / 4; i++) {
93 		*dest = le32_to_cpu(*src);
94 		dest++;
95 		src++;
96 	}
97 }
98 #else
99 static void wlan_crypto_endianness_conversion(uint8_t *dest, uint8_t *src,
100 					      uint32_t keylen)
101 {
102 	qdf_mem_copy(dest, src, keylen);
103 }
104 #endif
105 
106 QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev,
107 				    struct wlan_crypto_key *req,
108 				    enum wlan_crypto_key_type key_type)
109 {
110 	struct set_key_params params = {0};
111 	struct wlan_objmgr_psoc *psoc;
112 	struct wlan_objmgr_pdev *pdev;
113 	enum cdp_sec_type sec_type = cdp_sec_type_none;
114 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
115 	struct cdp_pdev *txrx_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
116 	struct cdp_vdev *txrx_vdev;
117 	uint32_t pn[4] = {0, 0, 0, 0};
118 	struct cdp_peer *peer = NULL;
119 	uint8_t peer_id;
120 	uint8_t def_tx_idx;
121 	void *pdev_wmi_handle;
122 	bool pairwise;
123 	QDF_STATUS status;
124 
125 	pdev = wlan_vdev_get_pdev(vdev);
126 	if (!pdev) {
127 		target_if_err("Invalid PDEV");
128 		return QDF_STATUS_E_FAILURE;
129 	}
130 	psoc = wlan_vdev_get_psoc(vdev);
131 	if (!psoc) {
132 		target_if_err("Invalid PSOC");
133 		return QDF_STATUS_E_FAILURE;
134 	}
135 	soc = wlan_psoc_get_dp_handle(psoc);
136 	if (!soc) {
137 		target_if_err("Invalid DP Handle");
138 		return QDF_STATUS_E_FAILURE;
139 	}
140 	params.vdev_id = wlan_vdev_get_id(vdev);
141 	params.key_idx = req->keyix;
142 	qdf_mem_copy(params.peer_mac, req->macaddr, IEEE80211_ADDR_LEN);
143 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
144 	if (!pdev_wmi_handle) {
145 		target_if_err("Invalid PDEV WMI handle");
146 		return QDF_STATUS_E_FAILURE;
147 	}
148 
149 	params.key_flags = req->flags;
150 	if (key_type != WLAN_CRYPTO_KEY_TYPE_UNICAST) {
151 		pairwise = false;
152 		params.key_flags |= GROUP_USAGE;
153 
154 	} else {
155 		pairwise = true;
156 		params.key_flags |= PAIRWISE_USAGE;
157 	}
158 	qdf_mem_copy(&params.key_rsc_ctr,
159 		     &req->keyrsc[0], sizeof(uint64_t));
160 	txrx_vdev = (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
161 				(struct cdp_pdev *)txrx_pdev, params.vdev_id);
162 	peer = cdp_peer_find_by_addr(soc, txrx_pdev, req->macaddr, &peer_id);
163 
164 	if (!txrx_vdev) {
165 		target_if_err("Invalid txrx vdev");
166 		return QDF_STATUS_E_FAILURE;
167 	}
168 
169 	target_if_debug("key_type %d, mac: %02x:%02x:%02x:%02x:%02x:%02x",
170 			key_type, req->macaddr[0], req->macaddr[1],
171 			req->macaddr[2], req->macaddr[3], req->macaddr[4],
172 			req->macaddr[5]);
173 
174 	if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer) {
175 		target_if_err("Invalid peer");
176 		return QDF_STATUS_E_FAILURE;
177 	}
178 
179 	params.key_cipher = wlan_crypto_cipher_to_wmi_cipher(req->cipher_type);
180 	sec_type = wlan_crypto_cipher_to_cdp_sec_type(req->cipher_type);
181 	wlan_crypto_set_wapi_key(vdev, pairwise, req->cipher_type, &params);
182 
183 	switch (req->cipher_type) {
184 	case WLAN_CRYPTO_CIPHER_WEP:
185 		def_tx_idx = wlan_crypto_get_default_key_idx(vdev, false);
186 		if (pairwise && params.key_idx == def_tx_idx)
187 			params.key_flags |= TX_USAGE;
188 		else if ((vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) &&
189 			 (params.key_idx == def_tx_idx))
190 			params.key_flags |= TX_USAGE;
191 		break;
192 	case WLAN_CRYPTO_CIPHER_TKIP:
193 		params.key_txmic_len = WLAN_CRYPTO_MIC_LEN;
194 		params.key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
195 		break;
196 	default:
197 		break;
198 	}
199 
200 	wlan_crypto_endianness_conversion(&params.key_data[0],
201 					  &req->keyval[0],
202 					  req->keylen);
203 	params.key_len = req->keylen;
204 	if (peer) {
205 		/* Set PN check & security type in data path */
206 		cdp_set_pn_check(soc, txrx_vdev, peer, sec_type, pn);
207 		cdp_set_key(soc, peer, pairwise, (uint32_t *)(req->keyval +
208 			    WLAN_CRYPTO_IV_SIZE + WLAN_CRYPTO_MIC_LEN));
209 	} else {
210 		target_if_info("peer not found");
211 	}
212 
213 	target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id,
214 			params.key_idx, params.key_len);
215 	target_if_debug("peer mac %pM", params.peer_mac);
216 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG,
217 			   &params.key_rsc_ctr, sizeof(uint64_t));
218 	status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, &params);
219 
220 	return status;
221 }
222 
223 QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
224 {
225 	struct wlan_lmac_if_crypto_tx_ops *crypto;
226 
227 	if (!tx_ops) {
228 		target_if_err("txops NULL");
229 		return QDF_STATUS_E_FAILURE;
230 	}
231 	crypto = &tx_ops->crypto_tx_ops;
232 
233 	crypto->set_key = target_if_crypto_set_key;
234 
235 	return QDF_STATUS_SUCCESS;
236 }
237 
238