1/* 2 * Wireless USB Standard Definitions 3 * Event Size Tables 4 * 5 * Copyright (C) 2005-2006 Intel Corporation 6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 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 */ 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 * 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 * 77 * Make it packed, as we use it in some hw definitions. 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 * 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 */ 93struct 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 */ 105struct 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 */ 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 * WUSB IE: Channel Stop (WUSB1.0[7.5.8]) 128 * 129 * Tells devices the host is going to stop sending MMCs and will disappear. 130 */ 131struct 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 */ 142struct 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 */ 156struct 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 */ 167struct 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 */ 178struct wuie_host_disconnect { 179 struct wuie_hdr hdr; 180} __attribute__((packed)); 181 182/** 183 * WUSB Device Notification header (WUSB1.0[7.6]) 184 */ 185struct wusb_dn_hdr { 186 u8 bType; 187 u8 notifdata[]; 188} __attribute__((packed)); 189 190/** Device Notification codes (WUSB1.0[Table 7-54]) */ 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/** WUSB Device Notification Connect */ 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/** Device is alive (aka: pong) (WUSB1.0[7.6.7]) */ 224struct wusb_dn_alive { 225 struct wusb_dn_hdr hdr; 226} __attribute__((packed)); 227 228/** Device is disconnecting (WUSB1.0[7.6.2]) */ 229struct wusb_dn_disconnect { 230 struct wusb_dn_hdr hdr; 231} __attribute__((packed)); 232 233/* General constants */ 234enum { 235 WUSB_TRUST_TIMEOUT_MS = 4000, /* [WUSB] section 4.15.1 */ 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 * WUSB Crypto stuff (WUSB1.0[6]) 256 */ 257 258extern 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 */ 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 /* 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] */ 276struct 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] */ 284struct 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 */ 293struct 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 */ 302struct wusb_keydvt_out { 303 u8 kck[16]; 304 u8 ptk[16]; 305} __attribute__((packed)); 306 307/* Pseudo Random Function WUSB1.0[6.5] */ 308extern int wusb_crypto_init(void); 309extern void wusb_crypto_exit(void); 310extern 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 315static 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 323static 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 331static 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] */ 340static 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 */ 366static 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__ */ 376