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