xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/core/rtw_swcrypto.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #include <drv_types.h>
16 #include <aes.h>
17 #include <aes_siv.h>
18 #include <aes_wrap.h>
19 #include <sha256.h>
20 #include <wlancrypto_wrap.h>
21 
22 #if 0 //RTW_PHL_TX: mark un-finished codes for reading
23 int _rtw_core_ccmp_encrypt(u8 *key, u32 key_len, uint hdrlen, u8 *phdr, uint datalen, u8 *pdata)
24 {
25 	u8 *enc = NULL;
26 	size_t enc_len = 0;
27 
28 	if (key_len == 16) { /* 128 bits */
29 		core_ccmp_encrypt(key,
30 			hdrlen, phdr,
31 			datalen, pdata,
32 			(hdrlen == 26) ? (phdr + hdrlen - 2) : NULL,
33 			NULL, 0, &enc_len);
34 	} else if (key_len == 32) { /* 256 bits */
35 		core_ccmp_256_encrypt(key,
36 			hdrlen, phdr,
37 			datalen, pdata,
38 			(hdrlen == 26) ? (phdr + hdrlen - 2) : NULL,
39 			NULL, 0, &enc_len);
40 	}
41 
42 	return _SUCCESS;
43 }
44 #endif
45 
46 /**
47  * rtw_ccmp_encrypt -
48  * @key: the temporal key
49  * @hdrlen: mac header length
50  * @frame: the frame including the mac header, pn and payload
51  * @plen: payload length, i.e., length of the plain text, without PN and MIC
52  */
_rtw_ccmp_encrypt(_adapter * padapter,u8 * key,u32 key_len,uint hdrlen,u8 * frame,uint plen)53 int _rtw_ccmp_encrypt(_adapter *padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
54 {
55 	u8 *enc = NULL;
56 	size_t enc_len = 0;
57 
58 	if (key_len == 16) { /* 128 bits */
59 		enc = ccmp_encrypt(padapter, key,
60 			frame,
61 			hdrlen + plen,
62 			hdrlen,
63 			(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
64 			NULL, 0, &enc_len);
65 	} else if (key_len == 32) { /* 256 bits */
66 		enc = ccmp_256_encrypt(padapter, key,
67 			frame,
68 			hdrlen + plen,
69 			hdrlen,
70 			(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
71 			NULL, 0, &enc_len);
72 	}
73 
74 	if (enc == NULL) {
75 		RTW_INFO("Failed to encrypt CCMP(%u) frame", key_len);
76 		return _FAIL;
77 	}
78 
79 	/* Copy @enc back to @frame and free @enc */
80 	_rtw_memcpy(frame, enc, enc_len);
81 	rtw_mfree(enc, enc_len + AES_BLOCK_SIZE);
82 
83 	return _SUCCESS;
84 }
85 
86 
87 /**
88  * rtw_ccmp_decrypt -
89  * @key: the temporal key
90  * @hdrlen: length of the mac header
91  * @frame: the raw frame (@hdrlen + PN + enc_data + MIC)
92  * @plen: length of the frame (@hdrlen + PN + enc_data + MIC)
93  */
_rtw_ccmp_decrypt(_adapter * padapter,u8 * key,u32 key_len,uint hdrlen,u8 * frame,uint plen)94 int _rtw_ccmp_decrypt(_adapter * padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame,
95 	uint plen)
96 {
97 	u8 *plain = NULL;
98 	size_t plain_len = 0;
99 	const struct ieee80211_hdr *hdr;
100 
101 	hdr = (const struct ieee80211_hdr *)frame;
102 
103 	if (key_len == 16) { /* 128 bits */
104 		plain = ccmp_decrypt(padapter, key,
105 			hdr,
106 			frame + hdrlen, /* PN + enc_data + MIC */
107 			plen - hdrlen, /* PN + enc_data + MIC */
108 			&plain_len);
109 	} else if (key_len == 32) { /* 256 bits */
110 		plain = ccmp_256_decrypt(padapter, key,
111 			hdr,
112 			frame + hdrlen, /* PN + enc_data + MIC */
113 			plen - hdrlen, /* PN + enc_data + MIC */
114 			&plain_len);
115 	}
116 
117 	if (plain == NULL) {
118 		RTW_INFO("Failed to decrypt CCMP(%u) frame", key_len);
119 		return _FAIL;
120 	}
121 
122 	/* Copy @plain back to @frame and free @plain */
123 	_rtw_memcpy(frame + hdrlen + 8, plain, plain_len);
124 	rtw_mfree(plain, plen - hdrlen + AES_BLOCK_SIZE);
125 
126 	RTW_DBG_DUMP("ccmp_decrypt(): decrypted frame\n",
127 		frame, hdrlen + 8 + plen);
128 
129 	return _SUCCESS;
130 }
131 
132 
133 #ifdef CONFIG_RTW_MESH_AEK
134 /* wrapper to ase_siv_encrypt and aes_siv_decrypt */
_aes_siv_encrypt(const u8 * key,size_t key_len,const u8 * pw,size_t pwlen,size_t num_elem,const u8 * addr[],const size_t * len,u8 * out)135 int _aes_siv_encrypt(const u8 *key, size_t key_len,
136 	const u8 *pw, size_t pwlen,
137 	size_t num_elem, const u8 *addr[], const size_t *len, u8 *out)
138 {
139 	return aes_siv_encrypt(key, key_len, pw, pwlen, num_elem, addr, len, out);
140 }
_aes_siv_decrypt(const u8 * key,size_t key_len,const u8 * iv_crypt,size_t iv_c_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * out)141 int _aes_siv_decrypt(const u8 *key, size_t key_len,
142 	const u8 *iv_crypt, size_t iv_c_len,
143 	size_t num_elem, const u8 *addr[], const size_t *len, u8 *out)
144 {
145 	return aes_siv_decrypt(key, key_len, iv_crypt, iv_c_len, num_elem, addr, len, out);
146 }
147 #endif
148 
149 
150 /**
151  * _rtw_gcmp_encrypt -
152  * @key: the temporal key
153  * @hdrlen: mac header length
154  * @frame: the frame including the mac header, pn and payload
155  * @plen: payload length, i.e., length of the plain text, without PN and MIC
156  */
_rtw_gcmp_encrypt(_adapter * padapter,u8 * key,u32 key_len,uint hdrlen,u8 * frame,uint plen)157 int _rtw_gcmp_encrypt(_adapter * padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
158 {
159 	u8 *enc = NULL;
160 	size_t enc_len = 0;
161 
162 	enc = gcmp_encrypt(padapter, key, key_len,
163 		frame,
164 		hdrlen + plen,
165 		hdrlen,
166 		(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
167 		NULL, 0, &enc_len);
168 	if (enc == NULL) {
169 		RTW_INFO("Failed to encrypt GCMP frame");
170 		return _FAIL;
171 	}
172 
173 	/* Copy @enc back to @frame and free @enc */
174 	_rtw_memcpy(frame, enc, enc_len);
175 	rtw_mfree(enc, enc_len + AES_BLOCK_SIZE);
176 
177 	return _SUCCESS;
178 }
179 
180 
181 /**
182  * _rtw_gcmp_decrypt -
183  * @key: the temporal key
184  * @hdrlen: length of the mac header
185  * @frame: the raw frame (@hdrlen + PN + enc_data + MIC)
186  * @plen: length of the frame (@hdrlen + PN + enc_data + MIC)
187  */
_rtw_gcmp_decrypt(_adapter * padapter,u8 * key,u32 key_len,uint hdrlen,u8 * frame,uint plen)188 int _rtw_gcmp_decrypt(_adapter *padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
189 {
190 	u8 *plain = NULL;
191 	size_t plain_len = 0;
192 	const struct ieee80211_hdr *hdr;
193 
194 	hdr = (const struct ieee80211_hdr *)frame;
195 
196 	plain = gcmp_decrypt(padapter, key, key_len,
197 		hdr,
198 		frame + hdrlen, /* PN + enc_data + MIC */
199 		plen - hdrlen, /* PN + enc_data + MIC */
200 		&plain_len);
201 
202 	if (plain == NULL) {
203 		RTW_INFO("Failed to decrypt GCMP(%u) frame", key_len);
204 		return _FAIL;
205 	}
206 
207 	/* Copy @plain back to @frame and free @plain */
208 	_rtw_memcpy(frame + hdrlen + 8, plain, plain_len);
209 	rtw_mfree(plain, plen - hdrlen + AES_BLOCK_SIZE);
210 
211 	RTW_DBG_DUMP("gcmp_decipher(): decrypted frame\n",
212 		frame, hdrlen + 8 + plen);
213 
214 	return _SUCCESS;
215 }
216 
217 
218 #if  defined(CONFIG_IEEE80211W) | defined(CONFIG_TDLS)
_bip_ccmp_protect(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mic)219 u8 _bip_ccmp_protect(const u8 *key, size_t key_len,
220 	const u8 *data, size_t data_len, u8 *mic)
221 {
222 	u8 res = _SUCCESS;
223 
224 	if (key_len == 16) {
225 		if (omac1_aes_128(key, data, data_len, mic)) {
226 			res = _FAIL;
227 			RTW_ERR("%s : omac1_aes_128 fail!", __func__);
228 		}
229 	} else if (key_len == 32) {
230 		if (omac1_aes_256(key, data, data_len, mic)) {
231 			res = _FAIL;
232 			RTW_ERR("%s : omac1_aes_256 fail!", __func__);
233 		}
234 	} else {
235 		RTW_ERR("%s : key_len not match!", __func__);
236 		res = _FAIL;
237 	}
238 
239 	return  res;
240 }
241 
242 
_bip_gcmp_protect(u8 * whdr_pos,size_t len,const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mic)243 u8 _bip_gcmp_protect(u8 *whdr_pos, size_t len,
244 	const u8 *key, size_t key_len,
245 	const u8 *data, size_t data_len, u8 *mic)
246 {
247 	u8 res = _SUCCESS;
248 	u32 mic_len = 16;
249 	u8 nonce[12], *npos;
250 	const u8 *gcmp_ipn;
251 
252 	gcmp_ipn = whdr_pos + len - mic_len - 6;
253 
254 	/* Nonce: A2 | IPN */
255 	_rtw_memcpy(nonce, get_addr2_ptr(whdr_pos), ETH_ALEN);
256 	npos = nonce + ETH_ALEN;
257 	*npos++ = gcmp_ipn[5];
258 	*npos++ = gcmp_ipn[4];
259 	*npos++ = gcmp_ipn[3];
260 	*npos++ = gcmp_ipn[2];
261 	*npos++ = gcmp_ipn[1];
262 	*npos++ = gcmp_ipn[0];
263 
264 	if (aes_gmac(key, key_len, nonce, sizeof(nonce),
265 			data, data_len, mic)) {
266 		res = _FAIL;
267 		RTW_ERR("%s : aes_gmac fail!", __func__);
268 	}
269 
270 	return res;
271 }
272 #endif /* CONFIG_IEEE80211W */
273 
274 
275 #ifdef CONFIG_TDLS
_tdls_generate_tpk(void * sta,const u8 * own_addr,const u8 * bssid)276 void _tdls_generate_tpk(void *sta, const u8 *own_addr, const u8 *bssid)
277 {
278 	struct sta_info *psta = (struct sta_info *)sta;
279 	u8 *SNonce = psta->SNonce;
280 	u8 *ANonce = psta->ANonce;
281 
282 	u8 key_input[SHA256_MAC_LEN];
283 	const u8 *nonce[2];
284 	size_t len[2];
285 	u8 data[3 * ETH_ALEN];
286 
287 	/* IEEE Std 802.11z-2010 8.5.9.1:
288 	 * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
289 	 */
290 	len[0] = 32;
291 	len[1] = 32;
292 	if (_rtw_memcmp2(SNonce, ANonce, 32) < 0) {
293 		nonce[0] = SNonce;
294 		nonce[1] = ANonce;
295 	} else {
296 		nonce[0] = ANonce;
297 		nonce[1] = SNonce;
298 	}
299 
300 	sha256_vector(2, nonce, len, key_input);
301 
302 	/*
303 	 * TPK = KDF-Hash-Length(TPK-Key-Input, "TDLS PMK",
304 	 *	min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID)
305 	 */
306 
307 	if (_rtw_memcmp2(own_addr, psta->phl_sta->mac_addr, ETH_ALEN) < 0) {
308 		_rtw_memcpy(data, own_addr, ETH_ALEN);
309 		_rtw_memcpy(data + ETH_ALEN, psta->phl_sta->mac_addr, ETH_ALEN);
310 	} else {
311 		_rtw_memcpy(data, psta->phl_sta->mac_addr, ETH_ALEN);
312 		_rtw_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
313 	}
314 
315 	_rtw_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
316 
317 	sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), (u8 *)&psta->tpk, sizeof(psta->tpk));
318 }
319 #endif /* CONFIG_TDLS */
320