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