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