target_if_crypto.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for
  6. * any purpose with or without fee is hereby granted, provided that the
  7. * above copyright notice and this permission notice appear in all
  8. * copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  11. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  12. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  13. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. * PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. /**
  20. * DOC: offload lmac interface APIs definitions for crypto
  21. */
  22. #include <qdf_mem.h>
  23. #include <qdf_status.h>
  24. #include <target_if_crypto.h>
  25. #include <wmi_unified_priv.h>
  26. #include <wmi_unified_param.h>
  27. #include <wlan_objmgr_psoc_obj.h>
  28. #include <target_if.h>
  29. #include <wlan_crypto_global_def.h>
  30. #include <wlan_crypto_global_api.h>
  31. #include <wlan_objmgr_vdev_obj.h>
  32. #include <cdp_txrx_cmn_struct.h>
  33. #include <cds_api.h>
  34. #include <cdp_txrx_cmn.h>
  35. #include <wmi_unified_api.h>
  36. #include <wmi_unified_crypto_api.h>
  37. #include <cdp_txrx_peer_ops.h>
  38. #include <wlan_objmgr_pdev_obj.h>
  39. #include <wlan_objmgr_peer_obj.h>
  40. #include "wlan_crypto_def_i.h"
  41. #include "wlan_crypto_obj_mgr_i.h"
  42. #ifdef FEATURE_WLAN_WAPI
  43. #ifdef FEATURE_WAPI_BIG_ENDIAN
  44. /*
  45. * All lithium firmware expects WAPI in big endian
  46. * format , whereas helium firmware's expect otherwise
  47. */
  48. static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
  49. bool pairwise,
  50. enum wlan_crypto_cipher_type cipher_type,
  51. struct set_key_params *params)
  52. {
  53. static const unsigned char tx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
  54. 0x36, 0x5c, 0x36, 0x5c, 0x36,
  55. 0x5c, 0x36, 0x5c, 0x36, 0x5c,
  56. 0x36};
  57. static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
  58. 0x36, 0x5c, 0x36, 0x5c, 0x36,
  59. 0x5c, 0x36, 0x5c, 0x36, 0x5c,
  60. 0x37};
  61. if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 &&
  62. cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4)
  63. return;
  64. if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE ||
  65. vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE) {
  66. qdf_mem_copy(&params->rx_iv, &tx_iv,
  67. WLAN_CRYPTO_WAPI_IV_SIZE);
  68. qdf_mem_copy(params->tx_iv, &rx_iv,
  69. WLAN_CRYPTO_WAPI_IV_SIZE);
  70. } else {
  71. qdf_mem_copy(params->rx_iv, &rx_iv,
  72. WLAN_CRYPTO_WAPI_IV_SIZE);
  73. qdf_mem_copy(params->tx_iv, &tx_iv,
  74. WLAN_CRYPTO_WAPI_IV_SIZE);
  75. }
  76. params->key_txmic_len = WLAN_CRYPTO_MIC_LEN;
  77. params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
  78. }
  79. #else
  80. static void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
  81. bool pairwise,
  82. enum wlan_crypto_cipher_type cipher_type,
  83. struct set_key_params *params)
  84. {
  85. static const unsigned char tx_iv[16] = {0x36, 0x5c, 0x36, 0x5c, 0x36,
  86. 0x5c, 0x36, 0x5c, 0x36, 0x5c,
  87. 0x36, 0x5c, 0x36, 0x5c, 0x36,
  88. 0x5c};
  89. static const unsigned char rx_iv[16] = {0x5c, 0x36, 0x5c, 0x36, 0x5c,
  90. 0x36, 0x5c, 0x36, 0x5c, 0x36,
  91. 0x5c, 0x36, 0x5c, 0x36, 0x5c,
  92. 0x37};
  93. if (cipher_type != WLAN_CRYPTO_CIPHER_WAPI_SMS4 &&
  94. cipher_type != WLAN_CRYPTO_CIPHER_WAPI_GCM4)
  95. return;
  96. qdf_mem_copy(&params->rx_iv, &rx_iv,
  97. WLAN_CRYPTO_WAPI_IV_SIZE);
  98. qdf_mem_copy(&params->tx_iv, &tx_iv,
  99. WLAN_CRYPTO_WAPI_IV_SIZE);
  100. if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) {
  101. if (pairwise)
  102. params->tx_iv[0] = 0x37;
  103. params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
  104. } else {
  105. if (!pairwise)
  106. params->rx_iv[WLAN_CRYPTO_WAPI_IV_SIZE - 1] = 0x36;
  107. }
  108. params->key_txmic_len = WLAN_CRYPTO_MIC_LEN;
  109. params->key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
  110. }
  111. #endif /* FEATURE_WAPI_BIG_ENDIAN */
  112. #else
  113. static inline void wlan_crypto_set_wapi_key(struct wlan_objmgr_vdev *vdev,
  114. bool pairwise,
  115. enum wlan_crypto_cipher_type cipher,
  116. struct set_key_params *params)
  117. {
  118. }
  119. #endif /* FEATURE_WLAN_WAPI */
  120. QDF_STATUS
  121. target_if_crypto_vdev_set_param(struct wlan_objmgr_psoc *psoc, uint32_t vdev_id,
  122. uint32_t param_id, uint32_t param_value)
  123. {
  124. wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
  125. struct vdev_set_params param = {0};
  126. if (!wmi_handle) {
  127. target_if_err("Invalid wmi handle");
  128. return QDF_STATUS_E_INVAL;
  129. }
  130. if (vdev_id >= WLAN_MAX_VDEVS) {
  131. target_if_err("vdev_id: %d is invalid, reject the req: param id %d val %d",
  132. vdev_id, param_id, param_value);
  133. return QDF_STATUS_E_INVAL;
  134. }
  135. param.vdev_id = vdev_id;
  136. param.param_id = param_id;
  137. param.param_value = param_value;
  138. return wmi_unified_vdev_set_param_send(wmi_handle, &param);
  139. }
  140. QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev,
  141. struct wlan_crypto_key *req,
  142. enum wlan_crypto_key_type key_type)
  143. {
  144. struct set_key_params params = {0};
  145. struct wlan_objmgr_psoc *psoc;
  146. struct wlan_objmgr_pdev *pdev;
  147. struct wlan_objmgr_peer *peer;
  148. enum cdp_sec_type sec_type = cdp_sec_type_none;
  149. enum wlan_peer_type peer_type = 0;
  150. void *soc = cds_get_context(QDF_MODULE_ID_SOC);
  151. uint32_t pn[4] = {0, 0, 0, 0};
  152. bool peer_exist = false;
  153. uint8_t def_tx_idx;
  154. wmi_unified_t pdev_wmi_handle;
  155. bool pairwise;
  156. QDF_STATUS status;
  157. pdev = wlan_vdev_get_pdev(vdev);
  158. if (!pdev) {
  159. target_if_err("Invalid PDEV");
  160. return QDF_STATUS_E_FAILURE;
  161. }
  162. psoc = wlan_vdev_get_psoc(vdev);
  163. if (!psoc) {
  164. target_if_err("Invalid PSOC");
  165. return QDF_STATUS_E_FAILURE;
  166. }
  167. soc = wlan_psoc_get_dp_handle(psoc);
  168. if (!soc) {
  169. target_if_err("Invalid DP Handle");
  170. return QDF_STATUS_E_FAILURE;
  171. }
  172. params.vdev_id = wlan_vdev_get_id(vdev);
  173. params.key_idx = req->keyix;
  174. qdf_mem_copy(params.peer_mac, req->macaddr, QDF_MAC_ADDR_SIZE);
  175. pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
  176. if (!pdev_wmi_handle) {
  177. target_if_err("Invalid PDEV WMI handle");
  178. return QDF_STATUS_E_FAILURE;
  179. }
  180. params.key_flags = req->flags;
  181. if (key_type != WLAN_CRYPTO_KEY_TYPE_UNICAST) {
  182. pairwise = false;
  183. params.key_flags |= GROUP_USAGE;
  184. } else {
  185. pairwise = true;
  186. params.key_flags |= PAIRWISE_USAGE;
  187. }
  188. qdf_mem_copy(&params.key_rsc_ctr,
  189. &req->keyrsc[0], sizeof(uint64_t));
  190. peer_exist = cdp_find_peer_exist(soc, pdev->pdev_objmgr.wlan_pdev_id,
  191. req->macaddr);
  192. peer = wlan_objmgr_get_peer_by_mac(psoc, req->macaddr, WLAN_CRYPTO_ID);
  193. if (peer) {
  194. peer_type = wlan_peer_get_peer_type(peer);
  195. if (peer_type == WLAN_PEER_RTT_PASN &&
  196. key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST)
  197. peer_exist = true;
  198. wlan_objmgr_peer_release_ref(peer, WLAN_CRYPTO_ID);
  199. }
  200. target_if_debug("key_type %d, mac: %02x:%02x:%02x:%02x:%02x:%02x",
  201. key_type, req->macaddr[0], req->macaddr[1],
  202. req->macaddr[2], req->macaddr[3], req->macaddr[4],
  203. req->macaddr[5]);
  204. if ((key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST) && !peer_exist) {
  205. target_if_err("Invalid peer");
  206. return QDF_STATUS_E_FAILURE;
  207. }
  208. params.key_cipher = wlan_crypto_cipher_to_wmi_cipher(req->cipher_type);
  209. sec_type = wlan_crypto_cipher_to_cdp_sec_type(req->cipher_type);
  210. wlan_crypto_set_wapi_key(vdev, pairwise, req->cipher_type, &params);
  211. switch (req->cipher_type) {
  212. case WLAN_CRYPTO_CIPHER_WEP:
  213. case WLAN_CRYPTO_CIPHER_WEP_40:
  214. case WLAN_CRYPTO_CIPHER_WEP_104:
  215. def_tx_idx = wlan_crypto_get_default_key_idx(vdev, false);
  216. if (pairwise && params.key_idx == def_tx_idx)
  217. params.key_flags |= TX_USAGE;
  218. else if ((vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) &&
  219. (params.key_idx == def_tx_idx))
  220. params.key_flags |= TX_USAGE;
  221. break;
  222. case WLAN_CRYPTO_CIPHER_TKIP:
  223. params.key_txmic_len = WLAN_CRYPTO_MIC_LEN;
  224. params.key_rxmic_len = WLAN_CRYPTO_MIC_LEN;
  225. break;
  226. default:
  227. break;
  228. }
  229. qdf_mem_copy(&params.key_data[0], &req->keyval[0], req->keylen);
  230. params.key_len = req->keylen;
  231. /* Set PN check & security type in data path */
  232. qdf_mem_copy(&pn[0], &params.key_rsc_ctr, sizeof(uint64_t));
  233. if (peer_type == WLAN_PEER_RTT_PASN)
  234. goto send_install_key;
  235. cdp_set_pn_check(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
  236. sec_type, pn);
  237. cdp_set_key_sec_type(soc, vdev->vdev_objmgr.vdev_id, req->macaddr,
  238. sec_type, pairwise);
  239. cdp_set_key(soc, vdev->vdev_objmgr.vdev_id, req->macaddr, pairwise,
  240. (uint32_t *)(req->keyval + WLAN_CRYPTO_IV_SIZE +
  241. WLAN_CRYPTO_MIC_LEN));
  242. send_install_key:
  243. target_if_debug("vdev_id:%d, key: idx:%d,len:%d", params.vdev_id,
  244. params.key_idx, params.key_len);
  245. target_if_debug("peer mac "QDF_MAC_ADDR_FMT,
  246. QDF_MAC_ADDR_REF(params.peer_mac));
  247. QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_CRYPTO, QDF_TRACE_LEVEL_DEBUG,
  248. &params.key_rsc_ctr, sizeof(uint64_t));
  249. status = wmi_unified_setup_install_key_cmd(pdev_wmi_handle, &params);
  250. /* Zero-out local key variables */
  251. qdf_mem_zero(&params, sizeof(struct set_key_params));
  252. return status;
  253. }
  254. /**
  255. * target_if_crypto_install_key_comp_evt_handler() - install key complete
  256. * handler
  257. * @handle: wma handle
  258. * @event: event data
  259. * @len: data length
  260. *
  261. * This event is sent by fw once WPA/WPA2 keys are installed in fw.
  262. *
  263. * Return: 0 for success or error code
  264. */
  265. static int
  266. target_if_crypto_install_key_comp_evt_handler(void *handle, uint8_t *event,
  267. uint32_t len)
  268. {
  269. struct wlan_crypto_comp_priv *priv_obj;
  270. struct wlan_objmgr_psoc *psoc;
  271. struct wlan_objmgr_vdev *vdev;
  272. struct wmi_install_key_comp_event params;
  273. QDF_STATUS status;
  274. wmi_unified_t wmi_handle;
  275. struct crypto_add_key_result result;
  276. if (!event || !handle) {
  277. target_if_err("invalid param");
  278. return -EINVAL;
  279. }
  280. psoc = target_if_get_psoc_from_scn_hdl(handle);
  281. if (!psoc) {
  282. target_if_err("psoc is null");
  283. return -EINVAL;
  284. }
  285. wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
  286. if (!wmi_handle) {
  287. target_if_err("invalid wmi handle");
  288. return -EINVAL;
  289. }
  290. status = wmi_extract_install_key_comp_event(wmi_handle, event,
  291. len, &params);
  292. if (QDF_IS_STATUS_ERROR(status)) {
  293. target_if_err("received invalid buf from target");
  294. return -EINVAL;
  295. }
  296. target_if_debug("vdev %d mac " QDF_MAC_ADDR_FMT " ix %x flags %x status %d",
  297. params.vdev_id,
  298. QDF_MAC_ADDR_REF(params.peer_macaddr),
  299. params.key_ix, params.key_flags, params.status);
  300. vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, params.vdev_id,
  301. WLAN_CRYPTO_ID);
  302. if (!vdev) {
  303. target_if_err("vdev %d is null", params.vdev_id);
  304. return -EINVAL;
  305. }
  306. priv_obj = wlan_get_vdev_crypto_obj(vdev);
  307. if (!priv_obj) {
  308. target_if_err("priv_obj is null");
  309. wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
  310. return -EINVAL;
  311. }
  312. result.vdev_id = params.vdev_id;
  313. result.key_ix = params.key_ix;
  314. result.key_flags = params.key_flags;
  315. result.status = params.status;
  316. qdf_mem_copy(result.peer_macaddr, params.peer_macaddr,
  317. QDF_MAC_ADDR_SIZE);
  318. if (priv_obj->add_key_cb)
  319. priv_obj->add_key_cb(priv_obj->add_key_ctx, &result);
  320. wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
  321. return 0;
  322. }
  323. static QDF_STATUS
  324. target_if_crypto_register_events(struct wlan_objmgr_psoc *psoc)
  325. {
  326. QDF_STATUS status;
  327. if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
  328. target_if_err("psoc or psoc->tgt_if_handle is null");
  329. return QDF_STATUS_E_INVAL;
  330. }
  331. status = wmi_unified_register_event_handler(
  332. get_wmi_unified_hdl_from_psoc(psoc),
  333. wmi_vdev_install_key_complete_event_id,
  334. target_if_crypto_install_key_comp_evt_handler,
  335. WMI_RX_WORK_CTX);
  336. if (QDF_IS_STATUS_ERROR(status)) {
  337. target_if_err("register_event_handler failed: err %d", status);
  338. return status;
  339. }
  340. return QDF_STATUS_SUCCESS;
  341. }
  342. static QDF_STATUS
  343. target_if_crypto_deregister_events(struct wlan_objmgr_psoc *psoc)
  344. {
  345. if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
  346. target_if_err("psoc or psoc->tgt_if_handle is null");
  347. return QDF_STATUS_E_INVAL;
  348. }
  349. wmi_unified_unregister_event_handler(
  350. get_wmi_unified_hdl_from_psoc(psoc),
  351. wmi_vdev_install_key_complete_event_id);
  352. return QDF_STATUS_SUCCESS;
  353. }
  354. static QDF_STATUS
  355. target_if_crypto_set_ltf_keyseed(struct wlan_objmgr_psoc *psoc,
  356. struct wlan_crypto_ltf_keyseed_data *data)
  357. {
  358. QDF_STATUS status;
  359. wmi_unified_t wmi = GET_WMI_HDL_FROM_PSOC(psoc);
  360. if (!psoc || !wmi) {
  361. target_if_err("%s is null", !psoc ? "psoc" : "wmi_handle");
  362. return QDF_STATUS_E_INVAL;
  363. }
  364. status = wmi_send_vdev_set_ltf_key_seed_cmd(wmi, data);
  365. if (QDF_IS_STATUS_ERROR(status))
  366. target_if_err("set LTF keyseed failed");
  367. return status;
  368. }
  369. QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
  370. {
  371. struct wlan_lmac_if_crypto_tx_ops *crypto;
  372. if (!tx_ops) {
  373. target_if_err("txops NULL");
  374. return QDF_STATUS_E_FAILURE;
  375. }
  376. crypto = &tx_ops->crypto_tx_ops;
  377. crypto->set_key = target_if_crypto_set_key;
  378. crypto->set_ltf_keyseed = target_if_crypto_set_ltf_keyseed;
  379. crypto->set_vdev_param = target_if_crypto_vdev_set_param;
  380. crypto->register_events = target_if_crypto_register_events;
  381. crypto->deregister_events = target_if_crypto_deregister_events;
  382. return QDF_STATUS_SUCCESS;
  383. }