1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
41
42
43
44
45struct wuie_hdr {
46 u8 bLength;
47 u8 bIEIdentifier;
48} __attribute__((packed));
49
50enum {
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
64
65
66
67
68
69#define WUIE_ELT_MAX 4
70
71
72
73
74
75
76
77
78
79struct wusb_ckhdid {
80 u8 data[16];
81} __attribute__((packed));
82
83static const struct wusb_ckhdid wusb_ckhdid_zero = { .data = { 0 } };
84
85#define WUSB_CKHDID_STRSIZE (3 * sizeof(struct wusb_ckhdid) + 1)
86
87
88
89
90
91
92
93struct wuie_host_info {
94 struct wuie_hdr hdr;
95 __le16 attributes;
96 struct wusb_ckhdid CHID;
97} __attribute__((packed));
98
99
100
101
102
103
104
105struct wuie_connect_ack {
106 struct wuie_hdr hdr;
107 struct {
108 struct wusb_ckhdid CDID;
109 u8 bDeviceAddress;
110 u8 bReserved;
111 } blk[WUIE_ELT_MAX];
112} __attribute__((packed));
113
114
115
116
117
118
119enum {
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
128
129
130
131struct wuie_channel_stop {
132 struct wuie_hdr hdr;
133 u8 attributes;
134 u8 timestamp[3];
135} __attribute__((packed));
136
137
138
139
140
141
142struct wuie_keep_alive {
143 struct wuie_hdr hdr;
144 u8 bDeviceAddress[WUIE_ELT_MAX];
145} __attribute__((packed));
146
147
148
149
150
151
152
153
154
155
156struct wuie_reset {
157 struct wuie_hdr hdr;
158 struct wusb_ckhdid CDID;
159} __attribute__((packed));
160
161
162
163
164
165
166
167struct wuie_disconnect {
168 struct wuie_hdr hdr;
169 u8 bDeviceAddress;
170 u8 padding;
171} __attribute__((packed));
172
173
174
175
176
177
178struct wuie_host_disconnect {
179 struct wuie_hdr hdr;
180} __attribute__((packed));
181
182
183
184
185struct wusb_dn_hdr {
186 u8 bType;
187 u8 notifdata[];
188} __attribute__((packed));
189
190
191enum 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
202struct wusb_dn_connect {
203 struct wusb_dn_hdr hdr;
204 __le16 attributes;
205 struct wusb_ckhdid CDID;
206} __attribute__((packed));
207
208static 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
213static 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
218static 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
224struct wusb_dn_alive {
225 struct wusb_dn_hdr hdr;
226} __attribute__((packed));
227
228
229struct wusb_dn_disconnect {
230 struct wusb_dn_hdr hdr;
231} __attribute__((packed));
232
233
234enum {
235 WUSB_TRUST_TIMEOUT_MS = 4000,
236};
237
238static 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
256
257
258extern const char *wusb_et_name(u8);
259
260
261
262
263
264static 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
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#define WUSB_KEY_INDEX_MAX 15
276
277
278struct aes_ccm_nonce {
279 u8 sfn[6];
280 u8 tkid[3];
281 struct uwb_dev_addr dest_addr;
282 struct uwb_dev_addr src_addr;
283} __attribute__((packed));
284
285
286struct aes_ccm_label {
287 u8 data[14];
288} __attribute__((packed));
289
290
291
292
293
294
295struct wusb_keydvt_in {
296 u8 hnonce[16];
297 u8 dnonce[16];
298} __attribute__((packed));
299
300
301
302
303
304struct wusb_keydvt_out {
305 u8 kck[16];
306 u8 ptk[16];
307} __attribute__((packed));
308
309
310extern int wusb_crypto_init(void);
311extern void wusb_crypto_exit(void);
312extern ssize_t wusb_prf(void *out, size_t out_size,
313 const u8 key[16], const struct aes_ccm_nonce *_n,
314 const struct aes_ccm_label *a,
315 const void *b, size_t blen, size_t len);
316
317static inline int wusb_prf_64(void *out, size_t out_size, const u8 key[16],
318 const struct aes_ccm_nonce *n,
319 const struct aes_ccm_label *a,
320 const void *b, size_t blen)
321{
322 return wusb_prf(out, out_size, key, n, a, b, blen, 64);
323}
324
325static inline int wusb_prf_128(void *out, size_t out_size, const u8 key[16],
326 const struct aes_ccm_nonce *n,
327 const struct aes_ccm_label *a,
328 const void *b, size_t blen)
329{
330 return wusb_prf(out, out_size, key, n, a, b, blen, 128);
331}
332
333static inline int wusb_prf_256(void *out, size_t out_size, const u8 key[16],
334 const struct aes_ccm_nonce *n,
335 const struct aes_ccm_label *a,
336 const void *b, size_t blen)
337{
338 return wusb_prf(out, out_size, key, n, a, b, blen, 256);
339}
340
341
342static inline int wusb_key_derive(struct wusb_keydvt_out *keydvt_out,
343 const u8 key[16],
344 const struct aes_ccm_nonce *n,
345 const struct wusb_keydvt_in *keydvt_in)
346{
347 const struct aes_ccm_label a = { .data = "Pair-wise keys" };
348 return wusb_prf_256(keydvt_out, sizeof(*keydvt_out), key, n, &a,
349 keydvt_in, sizeof(*keydvt_in));
350}
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368static inline int wusb_oob_mic(u8 mic_out[8], const u8 key[16],
369 const struct aes_ccm_nonce *n,
370 const struct usb_handshake *hs)
371{
372 const struct aes_ccm_label a = { .data = "out-of-bandMIC" };
373 return wusb_prf_64(mic_out, 8, key, n, &a,
374 hs, sizeof(*hs) - sizeof(hs->MIC));
375}
376
377#endif
378