]>
Commit | Line | Data |
---|---|---|
c7f73648 IPG |
1 | /* |
2 | * Wireless USB Standard Definitions | |
3 | * Event Size Tables | |
4 | * | |
5 | * Copyright (C) 2005-2006 Intel Corporation | |
6 | * Inaky Perez-Gonzalez <[email protected]> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License version | |
10 | * 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
20 | * 02110-1301, USA. | |
21 | * | |
22 | * | |
23 | * FIXME: docs | |
24 | * FIXME: organize properly, group logically | |
25 | * | |
26 | * All the event structures are defined in uwb/spec.h, as they are | |
27 | * common to the WHCI and WUSB radio control interfaces. | |
28 | */ | |
29 | ||
30 | #ifndef __WUSB_H__ | |
31 | #define __WUSB_H__ | |
32 | ||
33 | #include <linux/types.h> | |
34 | #include <linux/kernel.h> | |
35 | #include <linux/uwb/spec.h> | |
36 | #include <linux/usb/ch9.h> | |
37 | #include <linux/param.h> | |
38 | ||
39 | /** | |
40 | * WUSB Information Element header | |
41 | * | |
42 | * I don't know why, they decided to make it different to the MBOA MAC | |
43 | * IE Header; beats me. | |
44 | */ | |
45 | struct wuie_hdr { | |
46 | u8 bLength; | |
47 | u8 bIEIdentifier; | |
48 | } __attribute__((packed)); | |
49 | ||
50 | enum { | |
51 | WUIE_ID_WCTA = 0x80, | |
52 | WUIE_ID_CONNECTACK, | |
53 | WUIE_ID_HOST_INFO, | |
54 | WUIE_ID_CHANGE_ANNOUNCE, | |
55 | WUIE_ID_DEVICE_DISCONNECT, | |
56 | WUIE_ID_HOST_DISCONNECT, | |
57 | WUIE_ID_KEEP_ALIVE = 0x89, | |
58 | WUIE_ID_ISOCH_DISCARD, | |
59 | WUIE_ID_RESET_DEVICE, | |
60 | }; | |
61 | ||
62 | /** | |
63 | * Maximum number of array elements in a WUSB IE. | |
64 | * | |
65 | * WUSB1.0[7.5 before table 7-38] says that in WUSB IEs that | |
66 | * are "arrays" have to limited to 4 elements. So we define it | |
67 | * like that to ease up and submit only the neeed size. | |
68 | */ | |
69 | #define WUIE_ELT_MAX 4 | |
70 | ||
71 | /** | |
72 | * Wrapper for the data that defines a CHID, a CDID or a CK | |
73 | * | |
74 | * WUSB defines that CHIDs, CDIDs and CKs are a 16 byte string of | |
75 | * data. In order to avoid confusion and enforce types, we wrap it. | |
76 | * | |
6070d81e | 77 | * Make it packed, as we use it in some hw definitions. |
c7f73648 IPG |
78 | */ |
79 | struct wusb_ckhdid { | |
80 | u8 data[16]; | |
81 | } __attribute__((packed)); | |
82 | ||
39db4b8d | 83 | static const struct wusb_ckhdid wusb_ckhdid_zero = { .data = { 0 } }; |
c7f73648 IPG |
84 | |
85 | #define WUSB_CKHDID_STRSIZE (3 * sizeof(struct wusb_ckhdid) + 1) | |
86 | ||
87 | /** | |
88 | * WUSB IE: Host Information (WUSB1.0[7.5.2]) | |
89 | * | |
90 | * Used to provide information about the host to the Wireless USB | |
91 | * devices in range (CHID can be used as an ASCII string). | |
92 | */ | |
93 | struct wuie_host_info { | |
94 | struct wuie_hdr hdr; | |
95 | __le16 attributes; | |
96 | struct wusb_ckhdid CHID; | |
97 | } __attribute__((packed)); | |
98 | ||
99 | /** | |
100 | * WUSB IE: Connect Ack (WUSB1.0[7.5.1]) | |
101 | * | |
102 | * Used to acknowledge device connect requests. See note for | |
103 | * WUIE_ELT_MAX. | |
104 | */ | |
105 | struct wuie_connect_ack { | |
106 | struct wuie_hdr hdr; | |
107 | struct { | |
108 | struct wusb_ckhdid CDID; | |
109 | u8 bDeviceAddress; /* 0 means unused */ | |
110 | u8 bReserved; | |
111 | } blk[WUIE_ELT_MAX]; | |
112 | } __attribute__((packed)); | |
113 | ||
114 | /** | |
115 | * WUSB IE Host Information Element, Connect Availability | |
116 | * | |
117 | * WUSB1.0[7.5.2], bmAttributes description | |
118 | */ | |
119 | enum { | |
120 | WUIE_HI_CAP_RECONNECT = 0, | |
121 | WUIE_HI_CAP_LIMITED, | |
122 | WUIE_HI_CAP_RESERVED, | |
123 | WUIE_HI_CAP_ALL, | |
124 | }; | |
125 | ||
126 | /** | |
127 | * WUSB IE: Channel Stop (WUSB1.0[7.5.8]) | |
128 | * | |
25985edc | 129 | * Tells devices the host is going to stop sending MMCs and will disappear. |
c7f73648 IPG |
130 | */ |
131 | struct wuie_channel_stop { | |
132 | struct wuie_hdr hdr; | |
133 | u8 attributes; | |
134 | u8 timestamp[3]; | |
135 | } __attribute__((packed)); | |
136 | ||
137 | /** | |
138 | * WUSB IE: Keepalive (WUSB1.0[7.5.9]) | |
139 | * | |
140 | * Ask device(s) to send keepalives. | |
141 | */ | |
142 | struct wuie_keep_alive { | |
143 | struct wuie_hdr hdr; | |
144 | u8 bDeviceAddress[WUIE_ELT_MAX]; | |
145 | } __attribute__((packed)); | |
146 | ||
147 | /** | |
148 | * WUSB IE: Reset device (WUSB1.0[7.5.11]) | |
149 | * | |
150 | * Tell device to reset; in all truth, we can fit 4 CDIDs, but we only | |
151 | * use it for one at the time... | |
152 | * | |
153 | * In any case, this request is a wee bit silly: why don't they target | |
154 | * by address?? | |
155 | */ | |
156 | struct wuie_reset { | |
157 | struct wuie_hdr hdr; | |
158 | struct wusb_ckhdid CDID; | |
159 | } __attribute__((packed)); | |
160 | ||
161 | /** | |
162 | * WUSB IE: Disconnect device (WUSB1.0[7.5.11]) | |
163 | * | |
164 | * Tell device to disconnect; we can fit 4 addresses, but we only use | |
165 | * it for one at the time... | |
166 | */ | |
167 | struct wuie_disconnect { | |
168 | struct wuie_hdr hdr; | |
169 | u8 bDeviceAddress; | |
170 | u8 padding; | |
171 | } __attribute__((packed)); | |
172 | ||
173 | /** | |
174 | * WUSB IE: Host disconnect ([WUSB] section 7.5.5) | |
175 | * | |
176 | * Tells all connected devices to disconnect. | |
177 | */ | |
178 | struct wuie_host_disconnect { | |
179 | struct wuie_hdr hdr; | |
180 | } __attribute__((packed)); | |
181 | ||
182 | /** | |
183 | * WUSB Device Notification header (WUSB1.0[7.6]) | |
184 | */ | |
185 | struct wusb_dn_hdr { | |
186 | u8 bType; | |
187 | u8 notifdata[]; | |
188 | } __attribute__((packed)); | |
189 | ||
190 | /** Device Notification codes (WUSB1.0[Table 7-54]) */ | |
191 | enum WUSB_DN { | |
192 | WUSB_DN_CONNECT = 0x01, | |
193 | WUSB_DN_DISCONNECT = 0x02, | |
194 | WUSB_DN_EPRDY = 0x03, | |
195 | WUSB_DN_MASAVAILCHANGED = 0x04, | |
196 | WUSB_DN_RWAKE = 0x05, | |
197 | WUSB_DN_SLEEP = 0x06, | |
198 | WUSB_DN_ALIVE = 0x07, | |
199 | }; | |
200 | ||
201 | /** WUSB Device Notification Connect */ | |
202 | struct wusb_dn_connect { | |
203 | struct wusb_dn_hdr hdr; | |
204 | __le16 attributes; | |
205 | struct wusb_ckhdid CDID; | |
206 | } __attribute__((packed)); | |
207 | ||
208 | static inline int wusb_dn_connect_prev_dev_addr(const struct wusb_dn_connect *dn) | |
209 | { | |
210 | return le16_to_cpu(dn->attributes) & 0xff; | |
211 | } | |
212 | ||
213 | static inline int wusb_dn_connect_new_connection(const struct wusb_dn_connect *dn) | |
214 | { | |
215 | return (le16_to_cpu(dn->attributes) >> 8) & 0x1; | |
216 | } | |
217 | ||
218 | static inline int wusb_dn_connect_beacon_behavior(const struct wusb_dn_connect *dn) | |
219 | { | |
220 | return (le16_to_cpu(dn->attributes) >> 9) & 0x03; | |
221 | } | |
222 | ||
223 | /** Device is alive (aka: pong) (WUSB1.0[7.6.7]) */ | |
224 | struct wusb_dn_alive { | |
225 | struct wusb_dn_hdr hdr; | |
226 | } __attribute__((packed)); | |
227 | ||
228 | /** Device is disconnecting (WUSB1.0[7.6.2]) */ | |
229 | struct wusb_dn_disconnect { | |
230 | struct wusb_dn_hdr hdr; | |
231 | } __attribute__((packed)); | |
232 | ||
233 | /* General constants */ | |
234 | enum { | |
235 | WUSB_TRUST_TIMEOUT_MS = 4000, /* [WUSB] section 4.15.1 */ | |
236 | }; | |
237 | ||
238 | static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, | |
239 | const struct wusb_ckhdid *ckhdid) | |
240 | { | |
241 | return scnprintf(pr_ckhdid, size, | |
242 | "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " | |
243 | "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", | |
244 | ckhdid->data[0], ckhdid->data[1], | |
245 | ckhdid->data[2], ckhdid->data[3], | |
246 | ckhdid->data[4], ckhdid->data[5], | |
247 | ckhdid->data[6], ckhdid->data[7], | |
248 | ckhdid->data[8], ckhdid->data[9], | |
249 | ckhdid->data[10], ckhdid->data[11], | |
250 | ckhdid->data[12], ckhdid->data[13], | |
251 | ckhdid->data[14], ckhdid->data[15]); | |
252 | } | |
253 | ||
254 | /* | |
255 | * WUSB Crypto stuff (WUSB1.0[6]) | |
256 | */ | |
257 | ||
258 | extern const char *wusb_et_name(u8); | |
259 | ||
260 | /** | |
261 | * WUSB key index WUSB1.0[7.3.2.4], for usage when setting keys for | |
262 | * the host or the device. | |
263 | */ | |
264 | static inline u8 wusb_key_index(int index, int type, int originator) | |
265 | { | |
266 | return (originator << 6) | (type << 4) | index; | |
267 | } | |
268 | ||
269 | #define WUSB_KEY_INDEX_TYPE_PTK 0 /* for HWA only */ | |
270 | #define WUSB_KEY_INDEX_TYPE_ASSOC 1 | |
271 | #define WUSB_KEY_INDEX_TYPE_GTK 2 | |
272 | #define WUSB_KEY_INDEX_ORIGINATOR_HOST 0 | |
273 | #define WUSB_KEY_INDEX_ORIGINATOR_DEVICE 1 | |
274 | ||
275 | /* A CCM Nonce, defined in WUSB1.0[6.4.1] */ | |
276 | struct aes_ccm_nonce { | |
277 | u8 sfn[6]; /* Little Endian */ | |
278 | u8 tkid[3]; /* LE */ | |
279 | struct uwb_dev_addr dest_addr; | |
280 | struct uwb_dev_addr src_addr; | |
281 | } __attribute__((packed)); | |
282 | ||
283 | /* A CCM operation label, defined on WUSB1.0[6.5.x] */ | |
284 | struct aes_ccm_label { | |
285 | u8 data[14]; | |
286 | } __attribute__((packed)); | |
287 | ||
288 | /* | |
289 | * Input to the key derivation sequence defined in | |
290 | * WUSB1.0[6.5.1]. Rest of the data is in the CCM Nonce passed to the | |
291 | * PRF function. | |
292 | */ | |
293 | struct wusb_keydvt_in { | |
294 | u8 hnonce[16]; | |
295 | u8 dnonce[16]; | |
296 | } __attribute__((packed)); | |
297 | ||
298 | /* | |
299 | * Output from the key derivation sequence defined in | |
300 | * WUSB1.0[6.5.1]. | |
301 | */ | |
302 | struct wusb_keydvt_out { | |
303 | u8 kck[16]; | |
304 | u8 ptk[16]; | |
305 | } __attribute__((packed)); | |
306 | ||
307 | /* Pseudo Random Function WUSB1.0[6.5] */ | |
308 | extern int wusb_crypto_init(void); | |
309 | extern void wusb_crypto_exit(void); | |
310 | extern ssize_t wusb_prf(void *out, size_t out_size, | |
311 | const u8 key[16], const struct aes_ccm_nonce *_n, | |
312 | const struct aes_ccm_label *a, | |
313 | const void *b, size_t blen, size_t len); | |
314 | ||
315 | static inline int wusb_prf_64(void *out, size_t out_size, const u8 key[16], | |
316 | const struct aes_ccm_nonce *n, | |
317 | const struct aes_ccm_label *a, | |
318 | const void *b, size_t blen) | |
319 | { | |
320 | return wusb_prf(out, out_size, key, n, a, b, blen, 64); | |
321 | } | |
322 | ||
323 | static inline int wusb_prf_128(void *out, size_t out_size, const u8 key[16], | |
324 | const struct aes_ccm_nonce *n, | |
325 | const struct aes_ccm_label *a, | |
326 | const void *b, size_t blen) | |
327 | { | |
328 | return wusb_prf(out, out_size, key, n, a, b, blen, 128); | |
329 | } | |
330 | ||
331 | static inline int wusb_prf_256(void *out, size_t out_size, const u8 key[16], | |
332 | const struct aes_ccm_nonce *n, | |
333 | const struct aes_ccm_label *a, | |
334 | const void *b, size_t blen) | |
335 | { | |
336 | return wusb_prf(out, out_size, key, n, a, b, blen, 256); | |
337 | } | |
338 | ||
339 | /* Key derivation WUSB1.0[6.5.1] */ | |
340 | static inline int wusb_key_derive(struct wusb_keydvt_out *keydvt_out, | |
341 | const u8 key[16], | |
342 | const struct aes_ccm_nonce *n, | |
343 | const struct wusb_keydvt_in *keydvt_in) | |
344 | { | |
345 | const struct aes_ccm_label a = { .data = "Pair-wise keys" }; | |
346 | return wusb_prf_256(keydvt_out, sizeof(*keydvt_out), key, n, &a, | |
347 | keydvt_in, sizeof(*keydvt_in)); | |
348 | } | |
349 | ||
350 | /* | |
351 | * Out-of-band MIC Generation WUSB1.0[6.5.2] | |
352 | * | |
353 | * Compute the MIC over @key, @n and @hs and place it in @mic_out. | |
354 | * | |
355 | * @mic_out: Where to place the 8 byte MIC tag | |
356 | * @key: KCK from the derivation process | |
357 | * @n: CCM nonce, n->sfn == 0, TKID as established in the | |
358 | * process. | |
359 | * @hs: Handshake struct for phase 2 of the 4-way. | |
360 | * hs->bStatus and hs->bReserved are zero. | |
361 | * hs->bMessageNumber is 2 (WUSB1.0[7.3.2.5.2] | |
362 | * hs->dest_addr is the device's USB address padded with 0 | |
363 | * hs->src_addr is the hosts's UWB device address | |
364 | * hs->mic is ignored (as we compute that value). | |
365 | */ | |
366 | static inline int wusb_oob_mic(u8 mic_out[8], const u8 key[16], | |
367 | const struct aes_ccm_nonce *n, | |
368 | const struct usb_handshake *hs) | |
369 | { | |
370 | const struct aes_ccm_label a = { .data = "out-of-bandMIC" }; | |
371 | return wusb_prf_64(mic_out, 8, key, n, &a, | |
372 | hs, sizeof(*hs) - sizeof(hs->MIC)); | |
373 | } | |
374 | ||
375 | #endif /* #ifndef __WUSB_H__ */ |