xref: /wlan-driver/qca-wifi-host-cmn/umac/cmn_services/crypto/src/wlan_crypto_def_i.h (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: Private definitions for handling crypto params
22*5113495bSYour Name  */
23*5113495bSYour Name #ifndef _WLAN_CRYPTO_DEF_I_H_
24*5113495bSYour Name #define _WLAN_CRYPTO_DEF_I_H_
25*5113495bSYour Name 
26*5113495bSYour Name #include <wlan_cmn_ieee80211.h>
27*5113495bSYour Name #include "wlan_objmgr_pdev_obj.h"
28*5113495bSYour Name #include "wlan_crypto_global_def.h"
29*5113495bSYour Name #ifdef WLAN_CRYPTO_AES
30*5113495bSYour Name #include "wlan_crypto_aes_i.h"
31*5113495bSYour Name #endif
32*5113495bSYour Name 
33*5113495bSYour Name /* Number of bits per byte */
34*5113495bSYour Name #define CRYPTO_NBBY  8
35*5113495bSYour Name /* Default link id for legacy connection */
36*5113495bSYour Name #define CRYPTO_MAX_LINK_IDX 0xFF
37*5113495bSYour Name 
38*5113495bSYour Name /* Macros for handling unaligned memory accesses */
39*5113495bSYour Name 
wlan_crypto_get_be16(const uint8_t * a)40*5113495bSYour Name static inline uint16_t wlan_crypto_get_be16(const uint8_t *a)
41*5113495bSYour Name {
42*5113495bSYour Name 	return (a[0] << 8) | a[1];
43*5113495bSYour Name }
44*5113495bSYour Name 
wlan_crypto_put_be16(uint8_t * a,uint16_t val)45*5113495bSYour Name static inline void wlan_crypto_put_be16(uint8_t *a, uint16_t val)
46*5113495bSYour Name {
47*5113495bSYour Name 	a[0] = val >> 8;
48*5113495bSYour Name 	a[1] = val & 0xff;
49*5113495bSYour Name }
50*5113495bSYour Name 
wlan_crypto_get_le16(const uint8_t * a)51*5113495bSYour Name static inline uint16_t wlan_crypto_get_le16(const uint8_t *a)
52*5113495bSYour Name {
53*5113495bSYour Name 	return (a[1] << 8) | a[0];
54*5113495bSYour Name }
55*5113495bSYour Name 
wlan_crypto_put_le16(uint8_t * a,uint16_t val)56*5113495bSYour Name static inline void wlan_crypto_put_le16(uint8_t *a, uint16_t val)
57*5113495bSYour Name {
58*5113495bSYour Name 	a[1] = val >> 8;
59*5113495bSYour Name 	a[0] = val & 0xff;
60*5113495bSYour Name }
61*5113495bSYour Name 
wlan_crypto_get_be32(const uint8_t * a)62*5113495bSYour Name static inline uint32_t wlan_crypto_get_be32(const uint8_t *a)
63*5113495bSYour Name {
64*5113495bSYour Name 	return ((u32) a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
65*5113495bSYour Name }
66*5113495bSYour Name 
wlan_crypto_put_be32(uint8_t * a,uint32_t val)67*5113495bSYour Name static inline void wlan_crypto_put_be32(uint8_t *a, uint32_t val)
68*5113495bSYour Name {
69*5113495bSYour Name 	a[0] = (val >> 24) & 0xff;
70*5113495bSYour Name 	a[1] = (val >> 16) & 0xff;
71*5113495bSYour Name 	a[2] = (val >> 8) & 0xff;
72*5113495bSYour Name 	a[3] = val & 0xff;
73*5113495bSYour Name }
74*5113495bSYour Name 
wlan_crypto_get_le32(const uint8_t * a)75*5113495bSYour Name static inline uint32_t wlan_crypto_get_le32(const uint8_t *a)
76*5113495bSYour Name {
77*5113495bSYour Name 	return ((u32) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
78*5113495bSYour Name }
79*5113495bSYour Name 
wlan_crypto_put_le32(uint8_t * a,uint32_t val)80*5113495bSYour Name static inline void wlan_crypto_put_le32(uint8_t *a, uint32_t val)
81*5113495bSYour Name {
82*5113495bSYour Name 	a[3] = (val >> 24) & 0xff;
83*5113495bSYour Name 	a[2] = (val >> 16) & 0xff;
84*5113495bSYour Name 	a[1] = (val >> 8) & 0xff;
85*5113495bSYour Name 	a[0] = val & 0xff;
86*5113495bSYour Name }
87*5113495bSYour Name 
wlan_crypto_put_be64(u8 * a,u64 val)88*5113495bSYour Name static inline void wlan_crypto_put_be64(u8 *a, u64 val)
89*5113495bSYour Name {
90*5113495bSYour Name 	a[0] = val >> 56;
91*5113495bSYour Name 	a[1] = val >> 48;
92*5113495bSYour Name 	a[2] = val >> 40;
93*5113495bSYour Name 	a[3] = val >> 32;
94*5113495bSYour Name 	a[4] = val >> 24;
95*5113495bSYour Name 	a[5] = val >> 16;
96*5113495bSYour Name 	a[6] = val >> 8;
97*5113495bSYour Name 	a[7] = val & 0xff;
98*5113495bSYour Name }
99*5113495bSYour Name 
100*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_ALLOCKEY(tx_ops) \
101*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.allockey)
102*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_SETKEY(tx_ops) \
103*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.setkey)
104*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_DELKEY(tx_ops) \
105*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.delkey)
106*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_DEFAULTKEY(tx_ops) \
107*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.defaultkey)
108*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_SET_KEY(tx_ops) \
109*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.set_key)
110*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_SET_VDEV_PARAM(tx_ops) \
111*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.set_vdev_param)
112*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_GETPN(tx_ops) \
113*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.getpn)
114*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_SET_LTF_KEYSEED(tx_ops) \
115*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.set_ltf_keyseed)
116*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_REGISTER_EVENTS(tx_ops) \
117*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.register_events)
118*5113495bSYour Name #define WLAN_CRYPTO_TX_OPS_DEREGISTER_EVENTS(tx_ops) \
119*5113495bSYour Name 	((tx_ops)->crypto_tx_ops.deregister_events)
120*5113495bSYour Name 
121*5113495bSYour Name /* unaligned little endian access */
122*5113495bSYour Name #ifndef LE_READ_2
123*5113495bSYour Name #define LE_READ_2(p) \
124*5113495bSYour Name 	((uint16_t)                          \
125*5113495bSYour Name 	((((const uint8_t *)(p))[0]) |       \
126*5113495bSYour Name 	(((const uint8_t *)(p))[1] <<  8)))
127*5113495bSYour Name #endif
128*5113495bSYour Name 
129*5113495bSYour Name #ifndef LE_READ_4
130*5113495bSYour Name #define LE_READ_4(p)                   \
131*5113495bSYour Name 	((uint32_t)                          \
132*5113495bSYour Name 	((((const uint8_t *)(p))[0]) |       \
133*5113495bSYour Name 	(((const uint8_t *)(p))[1] <<  8) |  \
134*5113495bSYour Name 	(((const uint8_t *)(p))[2] << 16) |  \
135*5113495bSYour Name 	(((const uint8_t *)(p))[3] << 24)))
136*5113495bSYour Name #endif
137*5113495bSYour Name 
138*5113495bSYour Name #ifndef BE_READ_4
139*5113495bSYour Name #define BE_READ_4(p)                        \
140*5113495bSYour Name 	((uint32_t)                              \
141*5113495bSYour Name 	((((const uint8_t *)(p))[0] << 24) |     \
142*5113495bSYour Name 	(((const uint8_t *)(p))[1] << 16) |      \
143*5113495bSYour Name 	(((const uint8_t *)(p))[2] <<  8) |      \
144*5113495bSYour Name 	(((const uint8_t *)(p))[3])))
145*5113495bSYour Name #endif
146*5113495bSYour Name 
147*5113495bSYour Name #ifndef READ_6
148*5113495bSYour Name #define READ_6(b0, b1, b2, b3, b4, b5)  ({ \
149*5113495bSYour Name 	uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);\
150*5113495bSYour Name 	uint16_t iv16 = (b4 << 0) | (b5 << 8);\
151*5113495bSYour Name 	(((uint64_t)iv16) << 32) | iv32;\
152*5113495bSYour Name })
153*5113495bSYour Name #endif
154*5113495bSYour Name 
155*5113495bSYour Name #define OUI_SIZE   (4)
156*5113495bSYour Name #define WLAN_CRYPTO_ADDSHORT(frm, v)  \
157*5113495bSYour Name 	do {frm[0] = (v) & 0xff; frm[1] = (v) >> 8; frm += 2; } while (0)
158*5113495bSYour Name 
159*5113495bSYour Name #define	WLAN_CRYPTO_ADDSELECTOR(frm, sel) \
160*5113495bSYour Name 	do { \
161*5113495bSYour Name 		uint32_t value = sel;\
162*5113495bSYour Name 		qdf_mem_copy(frm, (uint8_t *)&value, OUI_SIZE); \
163*5113495bSYour Name 	frm += OUI_SIZE; } while (0)
164*5113495bSYour Name 
165*5113495bSYour Name #define WLAN_CRYPTO_SELECTOR(a, b, c, d) \
166*5113495bSYour Name 	((((uint32_t) (a)) << 24) | \
167*5113495bSYour Name 	 (((uint32_t) (b)) << 16) | \
168*5113495bSYour Name 	 (((uint32_t) (c)) << 8) | \
169*5113495bSYour Name 		(uint32_t) (d))
170*5113495bSYour Name 
171*5113495bSYour Name #define WPA_TYPE_OUI                    WLAN_WPA_SEL(WLAN_WPA_OUI_TYPE)
172*5113495bSYour Name 
173*5113495bSYour Name #define WLAN_CRYPTO_WAPI_IE_LEN      20
174*5113495bSYour Name #define WLAN_CRYPTO_WAPI_SMS4_CIPHER 0x01
175*5113495bSYour Name 
176*5113495bSYour Name #define WPA_AUTH_KEY_MGMT_NONE          WLAN_WPA_SEL(WLAN_ASE_NONE)
177*5113495bSYour Name #define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X WLAN_WPA_SEL(WLAN_ASE_8021X_UNSPEC)
178*5113495bSYour Name #define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X \
179*5113495bSYour Name 					WLAN_WPA_SEL(WLAN_ASE_8021X_PSK)
180*5113495bSYour Name #define WPA_AUTH_KEY_MGMT_CCKM WLAN_WPA_CCKM_AKM
181*5113495bSYour Name 
182*5113495bSYour Name #define WPA_CIPHER_SUITE_NONE   WLAN_WPA_SEL(WLAN_CSE_NONE)
183*5113495bSYour Name #define WPA_CIPHER_SUITE_WEP40  WLAN_WPA_SEL(WLAN_CSE_WEP40)
184*5113495bSYour Name #define WPA_CIPHER_SUITE_WEP104 WLAN_WPA_SEL(WLAN_CSE_WEP104)
185*5113495bSYour Name #define WPA_CIPHER_SUITE_TKIP   WLAN_WPA_SEL(WLAN_CSE_TKIP)
186*5113495bSYour Name #define WPA_CIPHER_SUITE_CCMP   WLAN_WPA_SEL(WLAN_CSE_CCMP)
187*5113495bSYour Name 
188*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_NONE          WLAN_RSN_SEL(0)
189*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X WLAN_RSN_SEL(1)
190*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X\
191*5113495bSYour Name 					WLAN_RSN_SEL(2)
192*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_802_1X     WLAN_RSN_SEL(3)
193*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_PSK        WLAN_RSN_SEL(4)
194*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_802_1X_SHA256\
195*5113495bSYour Name 					WLAN_RSN_SEL(5)
196*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_PSK_SHA256    WLAN_RSN_SEL(6)
197*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_WPS           WLAN_RSN_SEL(7)
198*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_SAE           WLAN_RSN_SEL(8)
199*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_SAE        WLAN_RSN_SEL(9)
200*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B\
201*5113495bSYour Name 					WLAN_RSN_SEL(11)
202*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192\
203*5113495bSYour Name 					WLAN_RSN_SEL(12)
204*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384\
205*5113495bSYour Name 					WLAN_RSN_SEL(13)
206*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FILS_SHA256   WLAN_RSN_SEL(14)
207*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FILS_SHA384   WLAN_RSN_SEL(15)
208*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_FILS_SHA256\
209*5113495bSYour Name 					WLAN_RSN_SEL(16)
210*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_FILS_SHA384\
211*5113495bSYour Name 					WLAN_RSN_SEL(17)
212*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_OWE           WLAN_RSN_SEL(18)
213*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_PSK_SHA384 WLAN_RSN_SEL(19)
214*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_PSK_SHA384    WLAN_RSN_SEL(20)
215*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_SAE_EXT_KEY   WLAN_RSN_SEL(24)
216*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY WLAN_RSN_SEL(25)
217*5113495bSYour Name 
218*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_CCKM          (WLAN_RSN_CCKM_AKM)
219*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_OSEN          (0x019a6f50)
220*5113495bSYour Name #define RSN_AUTH_KEY_MGMT_DPP           (WLAN_RSN_DPP_AKM)
221*5113495bSYour Name 
222*5113495bSYour Name #define RSN_CIPHER_SUITE_NONE           WLAN_RSN_SEL(WLAN_CSE_NONE)
223*5113495bSYour Name #define RSN_CIPHER_SUITE_WEP40          WLAN_RSN_SEL(WLAN_CSE_WEP40)
224*5113495bSYour Name #define RSN_CIPHER_SUITE_TKIP           WLAN_RSN_SEL(WLAN_CSE_TKIP)
225*5113495bSYour Name #define RSN_CIPHER_SUITE_WEP104         WLAN_RSN_SEL(WLAN_CSE_WEP104)
226*5113495bSYour Name #define RSN_CIPHER_SUITE_CCMP           WLAN_RSN_SEL(WLAN_CSE_CCMP)
227*5113495bSYour Name #define RSN_CIPHER_SUITE_AES_CMAC       WLAN_RSN_SEL(WLAN_CSE_AES_CMAC)
228*5113495bSYour Name #define RSN_CIPHER_SUITE_GCMP           WLAN_RSN_SEL(WLAN_CSE_GCMP_128)
229*5113495bSYour Name #define RSN_CIPHER_SUITE_GCMP_256       WLAN_RSN_SEL(WLAN_CSE_GCMP_256)
230*5113495bSYour Name #define RSN_CIPHER_SUITE_CCMP_256       WLAN_RSN_SEL(WLAN_CSE_CCMP_256)
231*5113495bSYour Name #define RSN_CIPHER_SUITE_BIP_GMAC_128   WLAN_RSN_SEL(WLAN_CSE_BIP_GMAC_128)
232*5113495bSYour Name #define RSN_CIPHER_SUITE_BIP_GMAC_256   WLAN_RSN_SEL(WLAN_CSE_BIP_GMAC_256)
233*5113495bSYour Name #define RSN_CIPHER_SUITE_BIP_CMAC_256   WLAN_RSN_SEL(WLAN_CSE_BIP_CMAC_256)
234*5113495bSYour Name 
235*5113495bSYour Name #define RESET_PARAM(__param)         ((__param) = 0)
236*5113495bSYour Name #define SET_PARAM(__param, __val)    ((__param) |= (1 << (__val)))
237*5113495bSYour Name #define HAS_PARAM(__param, __val)    ((__param) &  (1 << (__val)))
238*5113495bSYour Name #define CLEAR_PARAM(__param, __val)  ((__param) &= (~(1 << (__val))))
239*5113495bSYour Name 
240*5113495bSYour Name 
241*5113495bSYour Name #define RESET_AUTHMODE(_param)       ((_param)->authmodeset = 0)
242*5113495bSYour Name 
243*5113495bSYour Name #define SET_AUTHMODE(_param, _mode)  ((_param)->authmodeset |= (1 << (_mode)))
244*5113495bSYour Name #define HAS_AUTHMODE(_param, _mode)  ((_param)->authmodeset &  (1 << (_mode)))
245*5113495bSYour Name 
246*5113495bSYour Name #define AUTH_IS_OPEN(_param)   HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_OPEN)
247*5113495bSYour Name #define AUTH_IS_SHARED_KEY(_param)  \
248*5113495bSYour Name 				HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_SHARED)
249*5113495bSYour Name #define AUTH_IS_8021X(_param)  HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_8021X)
250*5113495bSYour Name #define AUTH_IS_WPA(_param)    HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_WPA)
251*5113495bSYour Name #define AUTH_IS_RSNA(_param)   HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_RSNA)
252*5113495bSYour Name #define AUTH_IS_CCKM(_param)   HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_CCKM)
253*5113495bSYour Name #define AUTH_IS_WAI(_param)    HAS_AUTHMODE((_param), WLAN_CRYPTO_AUTH_WAPI)
254*5113495bSYour Name #define AUTH_IS_WPA2(_param)   AUTH_IS_RSNA(_param)
255*5113495bSYour Name 
256*5113495bSYour Name #define AUTH_MATCH(_param1, _param2) \
257*5113495bSYour Name 		(((_param1)->authmodeset & (_param2)->authmodeset) != 0)
258*5113495bSYour Name 
259*5113495bSYour Name 
260*5113495bSYour Name #define RESET_UCAST_CIPHERS(_param)   ((_param)->ucastcipherset = 0)
261*5113495bSYour Name #define SET_UCAST_CIPHER(_param, _c)  ((_param)->ucastcipherset |= (1 << (_c)))
262*5113495bSYour Name #define HAS_UCAST_CIPHER(_param, _c)  ((_param)->ucastcipherset & (1 << (_c)))
263*5113495bSYour Name 
264*5113495bSYour Name #define UCIPHER_IS_CLEAR(_param)   \
265*5113495bSYour Name 		((_param)->ucastcipherset == 0)
266*5113495bSYour Name #define UCIPHER_IS_WEP(_param)     \
267*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WEP)
268*5113495bSYour Name #define UCIPHER_IS_TKIP(_param)    \
269*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_TKIP)
270*5113495bSYour Name #define UCIPHER_IS_CCMP128(_param) \
271*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CCM)
272*5113495bSYour Name #define UCIPHER_IS_CCMP256(_param) \
273*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CCM_256)
274*5113495bSYour Name #define UCIPHER_IS_GCMP128(_param) \
275*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GCM)
276*5113495bSYour Name #define UCIPHER_IS_GCMP256(_param) \
277*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GCM_256)
278*5113495bSYour Name #define UCIPHER_IS_SMS4(_param)    \
279*5113495bSYour Name 		HAS_UCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WAPI_SMS4)
280*5113495bSYour Name 
281*5113495bSYour Name #define RESET_MCAST_CIPHERS(_param)   ((_param)->mcastcipherset = 0)
282*5113495bSYour Name #define SET_MCAST_CIPHER(_param, _c)  ((_param)->mcastcipherset |= (1 << (_c)))
283*5113495bSYour Name #define HAS_MCAST_CIPHER(_param, _c)  ((_param)->mcastcipherset & (1 << (_c)))
284*5113495bSYour Name #define HAS_ANY_MCAST_CIPHER(_param)  ((_param)->mcastcipherset)
285*5113495bSYour Name #define CLEAR_MCAST_CIPHER(_param, _c)  \
286*5113495bSYour Name 			((_param)->mcastcipherset &= (~(1)<<(_c)))
287*5113495bSYour Name 
288*5113495bSYour Name #define MCIPHER_IS_CLEAR(_param)   \
289*5113495bSYour Name 		((_param)->mcastcipherset == 0)
290*5113495bSYour Name #define MCIPHER_IS_WEP(_param)     \
291*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WEP)
292*5113495bSYour Name #define MCIPHER_IS_TKIP(_param)    \
293*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_TKIP)
294*5113495bSYour Name #define MCIPHER_IS_CCMP128(_param) \
295*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CCM)
296*5113495bSYour Name #define MCIPHER_IS_CCMP256(_param) \
297*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CCM_256)
298*5113495bSYour Name #define MCIPHER_IS_GCMP128(_param) \
299*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GCM)
300*5113495bSYour Name #define MCIPHER_IS_GCMP256(_param) \
301*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GCM_256)
302*5113495bSYour Name #define MCIPHER_IS_SMS4(_param)    \
303*5113495bSYour Name 		HAS_MCAST_CIPHER((_param), WLAN_CRYPTO_CIPHER_WAPI_SMS4)
304*5113495bSYour Name 
305*5113495bSYour Name #define RESET_MGMT_CIPHERS(_param)   ((_param)->mgmtcipherset = 0)
306*5113495bSYour Name #define SET_MGMT_CIPHER(_param, _c)  ((_param)->mgmtcipherset |= (1 << (_c)))
307*5113495bSYour Name #define HAS_MGMT_CIPHER(_param, _c)  ((_param)->mgmtcipherset & (1 << (_c)))
308*5113495bSYour Name #define IS_MGMT_CIPHER(_c)      ((_c == WLAN_CRYPTO_CIPHER_AES_CMAC) || \
309*5113495bSYour Name 				 (_c == WLAN_CRYPTO_CIPHER_AES_CMAC_256) || \
310*5113495bSYour Name 				 (_c == WLAN_CRYPTO_CIPHER_AES_GMAC) || \
311*5113495bSYour Name 				 (_c == WLAN_CRYPTO_CIPHER_AES_GMAC_256))
312*5113495bSYour Name 
313*5113495bSYour Name #define IS_FILS_CIPHER(_c)      ((_c) == WLAN_CRYPTO_CIPHER_FILS_AEAD)
314*5113495bSYour Name 
315*5113495bSYour Name #define MGMT_CIPHER_IS_CLEAR(_param)   \
316*5113495bSYour Name 		((_param)->mgmtcipherset == 0)
317*5113495bSYour Name #define MGMT_CIPHER_IS_CMAC(_param)    \
318*5113495bSYour Name 		HAS_MGMT_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CMAC)
319*5113495bSYour Name #define MGMT_CIPHER_IS_CMAC256(_param) \
320*5113495bSYour Name 		HAS_MGMT_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_CMAC_256)
321*5113495bSYour Name #define MGMT_CIPHER_IS_GMAC(_param)    \
322*5113495bSYour Name 		HAS_MGMT_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GMAC)
323*5113495bSYour Name #define MGMT_CIPHER_IS_GMAC256(_param) \
324*5113495bSYour Name 		HAS_MGMT_CIPHER((_param), WLAN_CRYPTO_CIPHER_AES_GMAC_256)
325*5113495bSYour Name 
326*5113495bSYour Name #define RESET_KEY_MGMT(_param)   ((_param)->key_mgmt = 0)
327*5113495bSYour Name #define SET_KEY_MGMT(_param, _c)  ((_param)->key_mgmt |= (1 << (_c)))
328*5113495bSYour Name #define HAS_KEY_MGMT(_param, _c)  ((_param)->key_mgmt & (1 << (_c)))
329*5113495bSYour Name 
330*5113495bSYour Name #define UCAST_CIPHER_MATCH(_param1, _param2)    \
331*5113495bSYour Name 	(((_param1)->ucastcipherset & (_param2)->ucastcipherset) != 0)
332*5113495bSYour Name 
333*5113495bSYour Name #define MCAST_CIPHER_MATCH(_param1, _param2)    \
334*5113495bSYour Name 	(((_param1)->mcastcipherset & (_param2)->mcastcipherset) != 0)
335*5113495bSYour Name 
336*5113495bSYour Name #define MGMT_CIPHER_MATCH(_param1, _param2)    \
337*5113495bSYour Name 	(((_param1)->mgmtcipherset & (_param2)->mgmtcipherset) != 0)
338*5113495bSYour Name 
339*5113495bSYour Name #define KEY_MGMTSET_MATCH(_param1, _param2)      \
340*5113495bSYour Name 	(((_param1)->key_mgmt & (_param2)->key_mgmt) != 0 ||    \
341*5113495bSYour Name 	(!(_param1)->key_mgmt && !(_param2)->key_mgmt))
342*5113495bSYour Name 
343*5113495bSYour Name #define RESET_CIPHER_CAP(_param)   ((_param)->cipher_caps = 0)
344*5113495bSYour Name #define SET_CIPHER_CAP(_param, _c)  ((_param)->cipher_caps |= (1 << (_c)))
345*5113495bSYour Name #define HAS_CIPHER_CAP(_param, _c)  ((_param)->cipher_caps & (1 << (_c)))
346*5113495bSYour Name #define HAS_ANY_CIPHER_CAP(_param)  ((_param)->cipher_caps)
347*5113495bSYour Name 
348*5113495bSYour Name #define crypto_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_CRYPTO, params)
349*5113495bSYour Name #define crypto_info(params...) QDF_TRACE_INFO(QDF_MODULE_ID_CRYPTO, params)
350*5113495bSYour Name #define crypto_debug(params...) QDF_TRACE_DEBUG(QDF_MODULE_ID_CRYPTO, params)
351*5113495bSYour Name 
352*5113495bSYour Name /**
353*5113495bSYour Name  * struct wlan_crypto_mmie - MMIE IE
354*5113495bSYour Name  * @element_id:      element id
355*5113495bSYour Name  * @length:          length of the ie
356*5113495bSYour Name  * @key_id:          igtk key_id used
357*5113495bSYour Name  * @sequence_number: igtk PN number
358*5113495bSYour Name  * @mic:             MIC for the frame
359*5113495bSYour Name  *
360*5113495bSYour Name  * This structure represents Management MIC information element (IEEE 802.11w)
361*5113495bSYour Name  */
362*5113495bSYour Name struct wlan_crypto_mmie {
363*5113495bSYour Name 	uint8_t  element_id;
364*5113495bSYour Name 	uint8_t  length;
365*5113495bSYour Name 	uint16_t key_id;
366*5113495bSYour Name 	uint8_t  sequence_number[6];
367*5113495bSYour Name 	uint8_t  mic[16];
368*5113495bSYour Name } __packed;
369*5113495bSYour Name 
370*5113495bSYour Name /**
371*5113495bSYour Name  * struct crypto_add_key_result - add key result structure
372*5113495bSYour Name  * @vdev_id: unique id identifying the VDEV
373*5113495bSYour Name  * @key_ix: key index
374*5113495bSYour Name  * @key_flags: key flags
375*5113495bSYour Name  * @status: status of add key
376*5113495bSYour Name  * @peer_macaddr: MAC address of the peer
377*5113495bSYour Name  *
378*5113495bSYour Name  * Structure used for add key result.
379*5113495bSYour Name  */
380*5113495bSYour Name struct crypto_add_key_result {
381*5113495bSYour Name 	uint32_t vdev_id;
382*5113495bSYour Name 	uint32_t key_ix;
383*5113495bSYour Name 	uint32_t key_flags;
384*5113495bSYour Name 	uint32_t status;
385*5113495bSYour Name 	uint8_t peer_macaddr[QDF_MAC_ADDR_SIZE];
386*5113495bSYour Name };
387*5113495bSYour Name 
388*5113495bSYour Name /**
389*5113495bSYour Name  * typedef crypto_add_key_callback - add key callback
390*5113495bSYour Name  * @context: opaque context that the client can use to associate the
391*5113495bSYour Name  *  callback with the request
392*5113495bSYour Name  * @result: result of add key
393*5113495bSYour Name  */
394*5113495bSYour Name typedef void (*crypto_add_key_callback)(void *context,
395*5113495bSYour Name 					struct crypto_add_key_result *result);
396*5113495bSYour Name 
397*5113495bSYour Name /**
398*5113495bSYour Name  * struct wlan_crypto_comp_priv - crypto component private structure
399*5113495bSYour Name  * @crypto_params:    crypto params for the peer
400*5113495bSYour Name  * @crypto_key: crypto keys structure for the peer
401*5113495bSYour Name  * @fils_aead_set:    fils params for this peer
402*5113495bSYour Name  * @add_key_ctx: Opaque context to be used by the caller to associate the
403*5113495bSYour Name  *  add key request with the response
404*5113495bSYour Name  * @add_key_cb: Callback function to be called with the add key result
405*5113495bSYour Name  *
406*5113495bSYour Name  */
407*5113495bSYour Name struct wlan_crypto_comp_priv {
408*5113495bSYour Name 	struct wlan_crypto_params crypto_params;
409*5113495bSYour Name 	struct wlan_crypto_keys crypto_key;
410*5113495bSYour Name 	uint8_t fils_aead_set;
411*5113495bSYour Name 	void *add_key_ctx;
412*5113495bSYour Name 	crypto_add_key_callback add_key_cb;
413*5113495bSYour Name };
414*5113495bSYour Name 
415*5113495bSYour Name /**
416*5113495bSYour Name  * struct wlan_crypto_cipher - crypto cipher table
417*5113495bSYour Name  * @cipher_name: printable name
418*5113495bSYour Name  * @cipher:      cipher type WLAN_CRYPTO_CIPHER_*
419*5113495bSYour Name  * @header:      size of privacy header (bytes)
420*5113495bSYour Name  * @trailer:     size of privacy trailer (bytes)
421*5113495bSYour Name  * @miclen:      size of mic trailer (bytes)
422*5113495bSYour Name  * @keylen:      max key length
423*5113495bSYour Name  * @setkey:      function pointer for setkey
424*5113495bSYour Name  * @encap:       function pointer for encap
425*5113495bSYour Name  * @decap:       function pointer for decap
426*5113495bSYour Name  * @enmic:       function pointer for enmic
427*5113495bSYour Name  * @demic:       function pointer for demic
428*5113495bSYour Name  *
429*5113495bSYour Name  */
430*5113495bSYour Name struct wlan_crypto_cipher {
431*5113495bSYour Name 	const char *cipher_name;
432*5113495bSYour Name 	wlan_crypto_cipher_type cipher;
433*5113495bSYour Name 	const uint8_t   header;
434*5113495bSYour Name 	const uint8_t   trailer;
435*5113495bSYour Name 	const uint8_t   miclen;
436*5113495bSYour Name 	const uint32_t  keylen;
437*5113495bSYour Name 	QDF_STATUS(*setkey)(struct wlan_crypto_key *);
438*5113495bSYour Name 	QDF_STATUS(*encap)(struct wlan_crypto_key *,
439*5113495bSYour Name 				qdf_nbuf_t, uint8_t,  uint8_t);
440*5113495bSYour Name 	QDF_STATUS(*decap)(struct wlan_crypto_key *,
441*5113495bSYour Name 				qdf_nbuf_t, uint8_t,  uint8_t);
442*5113495bSYour Name 	QDF_STATUS(*enmic)(struct wlan_crypto_key *,
443*5113495bSYour Name 				qdf_nbuf_t, uint8_t,  uint8_t);
444*5113495bSYour Name 	QDF_STATUS(*demic)(struct wlan_crypto_key *,
445*5113495bSYour Name 				qdf_nbuf_t, uint8_t,  uint8_t);
446*5113495bSYour Name };
447*5113495bSYour Name 
448*5113495bSYour Name 
449*5113495bSYour Name /**
450*5113495bSYour Name  * wlan_crypto_is_data_protected - check is frame is protected or not
451*5113495bSYour Name  * @data: frame
452*5113495bSYour Name  *
453*5113495bSYour Name  * This function check is frame is protected or not
454*5113495bSYour Name  *
455*5113495bSYour Name  * Return: TRUE/FALSE
456*5113495bSYour Name  */
wlan_crypto_is_data_protected(const void * data)457*5113495bSYour Name static inline bool wlan_crypto_is_data_protected(const void *data)
458*5113495bSYour Name {
459*5113495bSYour Name 	const struct wlan_frame_hdr *hdr = (const struct wlan_frame_hdr *)data;
460*5113495bSYour Name 	if (hdr->i_fc[1] & WLAN_FC1_ISWEP)
461*5113495bSYour Name 		return true;
462*5113495bSYour Name 	else
463*5113495bSYour Name 		return false;
464*5113495bSYour Name }
465*5113495bSYour Name 
466*5113495bSYour Name /**
467*5113495bSYour Name  * ieee80211_hdrsize - calculate frame header size
468*5113495bSYour Name  * @data: frame
469*5113495bSYour Name  *
470*5113495bSYour Name  * This function calculate frame header size
471*5113495bSYour Name  *
472*5113495bSYour Name  * Return: header size of the frame
473*5113495bSYour Name  */
ieee80211_hdrsize(const void * data)474*5113495bSYour Name static inline uint8_t ieee80211_hdrsize(const void *data)
475*5113495bSYour Name {
476*5113495bSYour Name 	const struct wlan_frame_hdr *hdr = (const struct wlan_frame_hdr *)data;
477*5113495bSYour Name 	uint8_t size = sizeof(struct wlan_frame_hdr);
478*5113495bSYour Name 
479*5113495bSYour Name 	if ((hdr->i_fc[1] & WLAN_FC1_DIR_MASK)
480*5113495bSYour Name 				== (WLAN_FC1_DSTODS)) {
481*5113495bSYour Name 		size += QDF_MAC_ADDR_SIZE;
482*5113495bSYour Name 	}
483*5113495bSYour Name 
484*5113495bSYour Name 	if (((WLAN_FC0_GET_STYPE(hdr->i_fc[0])
485*5113495bSYour Name 			== WLAN_FC0_STYPE_QOS_DATA))) {
486*5113495bSYour Name 		size += sizeof(uint16_t);
487*5113495bSYour Name 		/* Qos frame with Order bit set indicates an HTC frame */
488*5113495bSYour Name 		if (hdr->i_fc[1] & WLAN_FC1_ORDER)
489*5113495bSYour Name 			size += (sizeof(uint8_t)*4);
490*5113495bSYour Name 	}
491*5113495bSYour Name 	if (((WLAN_FC0_GET_STYPE(hdr->i_fc[0])
492*5113495bSYour Name 			== WLAN_FC0_STYPE_ACTION))) {
493*5113495bSYour Name 		/* Action frame with Order bit set indicates an HTC frame */
494*5113495bSYour Name 		if (hdr->i_fc[1] & WLAN_FC1_ORDER)
495*5113495bSYour Name 			size += (sizeof(uint8_t)*4);
496*5113495bSYour Name 	}
497*5113495bSYour Name 	return size;
498*5113495bSYour Name }
499*5113495bSYour Name 
500*5113495bSYour Name /**
501*5113495bSYour Name  * ieee80211_hdrspace - calculate frame header size with padding
502*5113495bSYour Name  * @pdev: pdev
503*5113495bSYour Name  * @data: frame header
504*5113495bSYour Name  *
505*5113495bSYour Name  * This function returns the space occupied by the 802.11 header
506*5113495bSYour Name  * and any padding required by the driver. This works for a management
507*5113495bSYour Name  * or data frame.
508*5113495bSYour Name  *
509*5113495bSYour Name  * Return: header size of the frame with padding
510*5113495bSYour Name  */
511*5113495bSYour Name static inline uint8_t
ieee80211_hdrspace(struct wlan_objmgr_pdev * pdev,const void * data)512*5113495bSYour Name ieee80211_hdrspace(struct wlan_objmgr_pdev *pdev, const void *data)
513*5113495bSYour Name {
514*5113495bSYour Name 	uint8_t size = ieee80211_hdrsize(data);
515*5113495bSYour Name 
516*5113495bSYour Name 	if (wlan_pdev_nif_feat_cap_get(pdev, WLAN_PDEV_F_DATAPAD))
517*5113495bSYour Name 		size = roundup(size, sizeof(u_int32_t));
518*5113495bSYour Name 
519*5113495bSYour Name 	return size;
520*5113495bSYour Name }
521*5113495bSYour Name 
522*5113495bSYour Name /**
523*5113495bSYour Name  * wlan_get_tid - get tid of the frame
524*5113495bSYour Name  * @data: frame
525*5113495bSYour Name  *
526*5113495bSYour Name  * This function get tid of the frame
527*5113495bSYour Name  *
528*5113495bSYour Name  * Return: tid of the frame
529*5113495bSYour Name  */
wlan_get_tid(const void * data)530*5113495bSYour Name static inline int wlan_get_tid(const void *data)
531*5113495bSYour Name {
532*5113495bSYour Name 	const struct wlan_frame_hdr *hdr = (const struct wlan_frame_hdr *)data;
533*5113495bSYour Name 
534*5113495bSYour Name 	if (((WLAN_FC0_GET_STYPE(hdr->i_fc[0])
535*5113495bSYour Name 				== WLAN_FC0_STYPE_QOS_DATA))) {
536*5113495bSYour Name 		if ((hdr->i_fc[1] & WLAN_FC1_DIR_MASK)
537*5113495bSYour Name 					== (WLAN_FC1_DSTODS)) {
538*5113495bSYour Name 			return ((struct wlan_frame_hdr_qos_addr4 *)data)->i_qos[0]
539*5113495bSYour Name 							& WLAN_QOS_TID_MASK;
540*5113495bSYour Name 		} else {
541*5113495bSYour Name 			return ((struct wlan_frame_hdr_qos *)data)->i_qos[0]
542*5113495bSYour Name 							& WLAN_QOS_TID_MASK;
543*5113495bSYour Name 		}
544*5113495bSYour Name 	} else
545*5113495bSYour Name 		return WLAN_NONQOS_SEQ;
546*5113495bSYour Name }
547*5113495bSYour Name 
548*5113495bSYour Name struct crypto_psoc_priv_obj {
549*5113495bSYour Name 	/** @crypto_key_lock: lock for crypto key table */
550*5113495bSYour Name 	qdf_mutex_t crypto_key_lock;
551*5113495bSYour Name 	/** @crypto_key_lock: lock for crypto key table */
552*5113495bSYour Name 	qdf_atomic_t crypto_key_cnt;
553*5113495bSYour Name 	struct {
554*5113495bSYour Name 		/** @mask: mask bits */
555*5113495bSYour Name 		uint32_t mask;
556*5113495bSYour Name 		/** @idx_bits: index to shift bits */
557*5113495bSYour Name 		uint32_t idx_bits;
558*5113495bSYour Name 		/** @bins: crypto key table */
559*5113495bSYour Name 		TAILQ_HEAD(, wlan_crypto_key_entry) * bins;
560*5113495bSYour Name 	} crypto_key_holder;
561*5113495bSYour Name };
562*5113495bSYour Name 
563*5113495bSYour Name /**
564*5113495bSYour Name  * struct pdev_crypto - pdev object structure for crypto
565*5113495bSYour Name  * @pdev_obj: pdev object
566*5113495bSYour Name  */
567*5113495bSYour Name struct pdev_crypto {
568*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev_obj;
569*5113495bSYour Name };
570*5113495bSYour Name 
571*5113495bSYour Name /**
572*5113495bSYour Name  * wlan_crypto_add_key_entry() - Add a filled key entry to the hashing
573*5113495bSYour Name  * framework
574*5113495bSYour Name  * @psoc: PSOC pointer
575*5113495bSYour Name  * @new_entry: New entry
576*5113495bSYour Name  *
577*5113495bSYour Name  * Return: QDF_STATUS
578*5113495bSYour Name  */
579*5113495bSYour Name QDF_STATUS wlan_crypto_add_key_entry(struct wlan_objmgr_psoc *psoc,
580*5113495bSYour Name 				     struct wlan_crypto_key_entry *new_entry);
581*5113495bSYour Name 
582*5113495bSYour Name /**
583*5113495bSYour Name  * crypto_add_entry - add key entry to hashing framework
584*5113495bSYour Name  * @psoc: psoc handler
585*5113495bSYour Name  * @link_id: link id
586*5113495bSYour Name  * @mac_addr: mac addr
587*5113495bSYour Name  * @crypto_key: crypto key
588*5113495bSYour Name  * @key_index: key index
589*5113495bSYour Name  * Return: zero on success
590*5113495bSYour Name  */
591*5113495bSYour Name QDF_STATUS crypto_add_entry(struct crypto_psoc_priv_obj *psoc,
592*5113495bSYour Name 			    uint8_t link_id,
593*5113495bSYour Name 			    uint8_t *mac_addr,
594*5113495bSYour Name 			    struct wlan_crypto_key *crypto_key,
595*5113495bSYour Name 			    uint8_t key_index);
596*5113495bSYour Name /**
597*5113495bSYour Name  * crypto_hash_find_by_linkid_and_macaddr - find crypto entry by link id
598*5113495bSYour Name  * @psoc: psoc handler
599*5113495bSYour Name  * @link_id: link id
600*5113495bSYour Name  * @mac_addr: mac addr
601*5113495bSYour Name  * Return: crypto key entry on success
602*5113495bSYour Name  */
603*5113495bSYour Name struct
604*5113495bSYour Name wlan_crypto_key_entry * crypto_hash_find_by_linkid_and_macaddr(
605*5113495bSYour Name 				struct crypto_psoc_priv_obj *psoc,
606*5113495bSYour Name 				uint8_t link_id,
607*5113495bSYour Name 				uint8_t *mac_addr);
608*5113495bSYour Name 
609*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
610*5113495bSYour Name /**
611*5113495bSYour Name  * wlan_crypto_free_key_by_link_id - free key by link id
612*5113495bSYour Name  * @psoc: psoc handler
613*5113495bSYour Name  * @link_addr: link address
614*5113495bSYour Name  * @link_id: link id
615*5113495bSYour Name  */
616*5113495bSYour Name void wlan_crypto_free_key_by_link_id(struct wlan_objmgr_psoc *psoc,
617*5113495bSYour Name 				     struct qdf_mac_addr *link_addr,
618*5113495bSYour Name 				     uint8_t link_id);
619*5113495bSYour Name #else
620*5113495bSYour Name static inline
wlan_crypto_free_key_by_link_id(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * link_addr,uint8_t link_id)621*5113495bSYour Name void wlan_crypto_free_key_by_link_id(struct wlan_objmgr_psoc *psoc,
622*5113495bSYour Name 				     struct qdf_mac_addr *link_addr,
623*5113495bSYour Name 				     uint8_t link_id)
624*5113495bSYour Name {}
625*5113495bSYour Name #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
626*5113495bSYour Name #endif /* end of _WLAN_CRYPTO_DEF_I_H_ */
627