]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/usb/wusbcore/security.c
USB: add SPDX identifiers to all remaining files in drivers/usb/
[mirror_ubuntu-jammy-kernel.git] / drivers / usb / wusbcore / security.c
CommitLineData
5fd54ace 1// SPDX-License-Identifier: GPL-2.0
d59db761
IPG
2/*
3 * Wireless USB Host Controller
4 * Security support: encryption enablement, etc
5 *
6 * Copyright (C) 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 */
26#include <linux/types.h>
5a0e3ad6 27#include <linux/slab.h>
d59db761
IPG
28#include <linux/usb/ch9.h>
29#include <linux/random.h>
f940fcd8 30#include <linux/export.h>
d59db761 31#include "wusbhc.h"
b6565a07 32#include <asm/unaligned.h>
d59db761 33
471e42ad 34static void wusbhc_gtk_rekey_work(struct work_struct *work);
d59db761
IPG
35
36int wusbhc_sec_create(struct wusbhc *wusbhc)
37{
275e517c
TP
38 /*
39 * WQ is singlethread because we need to serialize rekey operations.
40 * Use a separate workqueue for security operations instead of the
41 * wusbd workqueue because security operations may need to communicate
42 * directly with downstream wireless devices using synchronous URBs.
43 * If a device is not responding, this could block other host
44 * controller operations.
45 */
46 wusbhc->wq_security = create_singlethread_workqueue("wusbd_security");
47 if (wusbhc->wq_security == NULL) {
48 pr_err("WUSB-core: Cannot create wusbd_security workqueue\n");
49 return -ENOMEM;
50 }
51
521aea08
RB
52 wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) +
53 sizeof(wusbhc->gtk.data);
d59db761
IPG
54 wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY;
55 wusbhc->gtk.descr.bReserved = 0;
471e42ad 56 wusbhc->gtk_index = 0;
d59db761 57
471e42ad 58 INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work);
d59db761
IPG
59
60 return 0;
61}
62
63
64/* Called when the HC is destroyed */
65void wusbhc_sec_destroy(struct wusbhc *wusbhc)
66{
275e517c 67 destroy_workqueue(wusbhc->wq_security);
d59db761
IPG
68}
69
70
71/**
72 * wusbhc_next_tkid - generate a new, currently unused, TKID
73 * @wusbhc: the WUSB host controller
74 * @wusb_dev: the device whose PTK the TKID is for
75 * (or NULL for a TKID for a GTK)
76 *
1076e7a4 77 * The generated TKID consists of two parts: the device's authenticated
d59db761
IPG
78 * address (or 0 or a GTK); and an incrementing number. This ensures
79 * that TKIDs cannot be shared between devices and by the time the
80 * incrementing number wraps around the older TKIDs will no longer be
81 * in use (a maximum of two keys may be active at any one time).
82 */
83static u32 wusbhc_next_tkid(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
84{
85 u32 *tkid;
86 u32 addr;
87
88 if (wusb_dev == NULL) {
89 tkid = &wusbhc->gtk_tkid;
90 addr = 0;
91 } else {
92 tkid = &wusb_port_by_idx(wusbhc, wusb_dev->port_idx)->ptk_tkid;
93 addr = wusb_dev->addr & 0x7f;
94 }
95
96 *tkid = (addr << 8) | ((*tkid + 1) & 0xff);
97
98 return *tkid;
99}
100
101static void wusbhc_generate_gtk(struct wusbhc *wusbhc)
102{
103 const size_t key_size = sizeof(wusbhc->gtk.data);
104 u32 tkid;
105
106 tkid = wusbhc_next_tkid(wusbhc, NULL);
107
108 wusbhc->gtk.descr.tTKID[0] = (tkid >> 0) & 0xff;
109 wusbhc->gtk.descr.tTKID[1] = (tkid >> 8) & 0xff;
110 wusbhc->gtk.descr.tTKID[2] = (tkid >> 16) & 0xff;
111
112 get_random_bytes(wusbhc->gtk.descr.bKeyData, key_size);
113}
114
115/**
116 * wusbhc_sec_start - start the security management process
117 * @wusbhc: the WUSB host controller
118 *
119 * Generate and set an initial GTK on the host controller.
120 *
121 * Called when the HC is started.
122 */
123int wusbhc_sec_start(struct wusbhc *wusbhc)
124{
125 const size_t key_size = sizeof(wusbhc->gtk.data);
126 int result;
127
128 wusbhc_generate_gtk(wusbhc);
129
130 result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
471e42ad 131 &wusbhc->gtk.descr.bKeyData, key_size);
d59db761
IPG
132 if (result < 0)
133 dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n",
134 result);
135
136 return result;
137}
138
139/**
140 * wusbhc_sec_stop - stop the security management process
141 * @wusbhc: the WUSB host controller
142 *
143 * Wait for any pending GTK rekeys to stop.
144 */
145void wusbhc_sec_stop(struct wusbhc *wusbhc)
146{
471e42ad 147 cancel_work_sync(&wusbhc->gtk_rekey_work);
d59db761
IPG
148}
149
150
151/** @returns encryption type name */
152const char *wusb_et_name(u8 x)
153{
154 switch (x) {
155 case USB_ENC_TYPE_UNSECURE: return "unsecure";
156 case USB_ENC_TYPE_WIRED: return "wired";
157 case USB_ENC_TYPE_CCM_1: return "CCM-1";
158 case USB_ENC_TYPE_RSA_1: return "RSA-1";
521aea08 159 default: return "unknown";
d59db761
IPG
160 }
161}
162EXPORT_SYMBOL_GPL(wusb_et_name);
163
164/*
165 * Set the device encryption method
166 *
167 * We tell the device which encryption method to use; we do this when
168 * setting up the device's security.
169 */
170static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value)
171{
172 int result;
173 struct device *dev = &usb_dev->dev;
174 struct wusb_dev *wusb_dev = usb_dev->wusb_dev;
175
176 if (value) {
177 value = wusb_dev->ccm1_etd.bEncryptionValue;
178 } else {
179 /* FIXME: should be wusb_dev->etd[UNSECURE].bEncryptionValue */
180 value = 0;
181 }
182 /* Set device's */
183 result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
184 USB_REQ_SET_ENCRYPTION,
185 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
7b3e3740 186 value, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
d59db761
IPG
187 if (result < 0)
188 dev_err(dev, "Can't set device's WUSB encryption to "
189 "%s (value %d): %d\n",
190 wusb_et_name(wusb_dev->ccm1_etd.bEncryptionType),
191 wusb_dev->ccm1_etd.bEncryptionValue, result);
192 return result;
193}
194
195/*
196 * Set the GTK to be used by a device.
197 *
198 * The device must be authenticated.
199 */
200static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
201{
202 struct usb_device *usb_dev = wusb_dev->usb_dev;
471e42ad
TP
203 u8 key_index = wusb_key_index(wusbhc->gtk_index,
204 WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST);
d59db761
IPG
205
206 return usb_control_msg(
207 usb_dev, usb_sndctrlpipe(usb_dev, 0),
208 USB_REQ_SET_DESCRIPTOR,
209 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
471e42ad 210 USB_DT_KEY << 8 | key_index, 0,
d59db761 211 &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
7b3e3740 212 USB_CTRL_SET_TIMEOUT);
d59db761
IPG
213}
214
215
216/* FIXME: prototype for adding security */
217int wusb_dev_sec_add(struct wusbhc *wusbhc,
218 struct usb_device *usb_dev, struct wusb_dev *wusb_dev)
219{
220 int result, bytes, secd_size;
221 struct device *dev = &usb_dev->dev;
e58ba01e 222 struct usb_security_descriptor *secd, *new_secd;
d59db761 223 const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL;
d59db761
IPG
224 const void *itr, *top;
225 char buf[64];
226
9279095a 227 secd = kmalloc(sizeof(*secd), GFP_KERNEL);
b41ecf9a
SP
228 if (secd == NULL) {
229 result = -ENOMEM;
230 goto out;
231 }
232
d59db761 233 result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
9279095a
DV
234 0, secd, sizeof(*secd));
235 if (result < sizeof(*secd)) {
d59db761
IPG
236 dev_err(dev, "Can't read security descriptor or "
237 "not enough data: %d\n", result);
b41ecf9a 238 goto out;
d59db761 239 }
b41ecf9a 240 secd_size = le16_to_cpu(secd->wTotalLength);
e58ba01e
AK
241 new_secd = krealloc(secd, secd_size, GFP_KERNEL);
242 if (new_secd == NULL) {
521aea08
RB
243 dev_err(dev,
244 "Can't allocate space for security descriptors\n");
fca0ca95 245 result = -ENOMEM;
b41ecf9a 246 goto out;
d59db761 247 }
e58ba01e 248 secd = new_secd;
d59db761 249 result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
b41ecf9a 250 0, secd, secd_size);
d59db761
IPG
251 if (result < secd_size) {
252 dev_err(dev, "Can't read security descriptor or "
253 "not enough data: %d\n", result);
b41ecf9a 254 goto out;
d59db761 255 }
d59db761 256 bytes = 0;
b41ecf9a
SP
257 itr = &secd[1];
258 top = (void *)secd + result;
d59db761
IPG
259 while (itr < top) {
260 etd = itr;
261 if (top - itr < sizeof(*etd)) {
262 dev_err(dev, "BUG: bad device security descriptor; "
263 "not enough data (%zu vs %zu bytes left)\n",
264 top - itr, sizeof(*etd));
265 break;
266 }
267 if (etd->bLength < sizeof(*etd)) {
268 dev_err(dev, "BUG: bad device encryption descriptor; "
269 "descriptor is too short "
270 "(%u vs %zu needed)\n",
271 etd->bLength, sizeof(*etd));
272 break;
273 }
274 itr += etd->bLength;
275 bytes += snprintf(buf + bytes, sizeof(buf) - bytes,
276 "%s (0x%02x/%02x) ",
277 wusb_et_name(etd->bEncryptionType),
278 etd->bEncryptionValue, etd->bAuthKeyIndex);
279 if (etd->bEncryptionType == USB_ENC_TYPE_CCM_1)
280 ccm1_etd = etd;
281 }
282 /* This code only supports CCM1 as of now. */
283 /* FIXME: user has to choose which sec mode to use?
284 * In theory we want CCM */
285 if (ccm1_etd == NULL) {
286 dev_err(dev, "WUSB device doesn't support CCM1 encryption, "
287 "can't use!\n");
288 result = -EINVAL;
b41ecf9a 289 goto out;
d59db761
IPG
290 }
291 wusb_dev->ccm1_etd = *ccm1_etd;
bce83697
DV
292 dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
293 buf, wusb_et_name(ccm1_etd->bEncryptionType),
294 ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
d59db761 295 result = 0;
d59db761 296out:
b41ecf9a 297 kfree(secd);
d59db761 298 return result;
d59db761
IPG
299}
300
301void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)
302{
303 /* Nothing so far */
304}
305
d59db761
IPG
306/**
307 * Update the address of an unauthenticated WUSB device
308 *
309 * Once we have successfully authenticated, we take it to addr0 state
310 * and then to a normal address.
311 *
312 * Before the device's address (as known by it) was usb_dev->devnum |
313 * 0x80 (unauthenticated address). With this we update it to usb_dev->devnum.
314 */
4656d5de 315int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
d59db761
IPG
316{
317 int result = -ENOMEM;
318 struct usb_device *usb_dev = wusb_dev->usb_dev;
319 struct device *dev = &usb_dev->dev;
320 u8 new_address = wusb_dev->addr & 0x7F;
321
322 /* Set address 0 */
323 result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
7b3e3740
TP
324 USB_REQ_SET_ADDRESS,
325 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
326 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
d59db761
IPG
327 if (result < 0) {
328 dev_err(dev, "auth failed: can't set address 0: %d\n",
329 result);
330 goto error_addr0;
331 }
332 result = wusb_set_dev_addr(wusbhc, wusb_dev, 0);
333 if (result < 0)
334 goto error_addr0;
6da9c990 335 usb_set_device_state(usb_dev, USB_STATE_DEFAULT);
d59db761
IPG
336 usb_ep0_reinit(usb_dev);
337
338 /* Set new (authenticated) address. */
339 result = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
7b3e3740
TP
340 USB_REQ_SET_ADDRESS,
341 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
342 new_address, 0, NULL, 0,
343 USB_CTRL_SET_TIMEOUT);
d59db761
IPG
344 if (result < 0) {
345 dev_err(dev, "auth failed: can't set address %u: %d\n",
346 new_address, result);
347 goto error_addr;
348 }
349 result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address);
350 if (result < 0)
351 goto error_addr;
6da9c990 352 usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
d59db761
IPG
353 usb_ep0_reinit(usb_dev);
354 usb_dev->authenticated = 1;
355error_addr:
356error_addr0:
357 return result;
358}
359
360/*
361 *
362 *
363 */
364/* FIXME: split and cleanup */
365int wusb_dev_4way_handshake(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev,
366 struct wusb_ckhdid *ck)
367{
368 int result = -ENOMEM;
369 struct usb_device *usb_dev = wusb_dev->usb_dev;
370 struct device *dev = &usb_dev->dev;
371 u32 tkid;
d59db761
IPG
372 struct usb_handshake *hs;
373 struct aes_ccm_nonce ccm_n;
374 u8 mic[8];
375 struct wusb_keydvt_in keydvt_in;
376 struct wusb_keydvt_out keydvt_out;
377
d5ca9db8 378 hs = kcalloc(3, sizeof(hs[0]), GFP_KERNEL);
d919523f 379 if (!hs)
d59db761 380 goto error_kzalloc;
d59db761
IPG
381
382 /* We need to turn encryption before beginning the 4way
383 * hshake (WUSB1.0[.3.2.2]) */
384 result = wusb_dev_set_encryption(usb_dev, 1);
385 if (result < 0)
386 goto error_dev_set_encryption;
387
388 tkid = wusbhc_next_tkid(wusbhc, wusb_dev);
d59db761
IPG
389
390 hs[0].bMessageNumber = 1;
391 hs[0].bStatus = 0;
b6565a07 392 put_unaligned_le32(tkid, hs[0].tTKID);
d59db761
IPG
393 hs[0].bReserved = 0;
394 memcpy(hs[0].CDID, &wusb_dev->cdid, sizeof(hs[0].CDID));
395 get_random_bytes(&hs[0].nonce, sizeof(hs[0].nonce));
521aea08 396 memset(hs[0].MIC, 0, sizeof(hs[0].MIC)); /* Per WUSB1.0[T7-22] */
d59db761 397
d59db761
IPG
398 result = usb_control_msg(
399 usb_dev, usb_sndctrlpipe(usb_dev, 0),
400 USB_REQ_SET_HANDSHAKE,
401 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
7b3e3740 402 1, 0, &hs[0], sizeof(hs[0]), USB_CTRL_SET_TIMEOUT);
d59db761
IPG
403 if (result < 0) {
404 dev_err(dev, "Handshake1: request failed: %d\n", result);
405 goto error_hs1;
406 }
407
408 /* Handshake 2, from the device -- need to verify fields */
409 result = usb_control_msg(
410 usb_dev, usb_rcvctrlpipe(usb_dev, 0),
411 USB_REQ_GET_HANDSHAKE,
412 USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
7b3e3740 413 2, 0, &hs[1], sizeof(hs[1]), USB_CTRL_GET_TIMEOUT);
d59db761
IPG
414 if (result < 0) {
415 dev_err(dev, "Handshake2: request failed: %d\n", result);
416 goto error_hs2;
417 }
d59db761
IPG
418
419 result = -EINVAL;
420 if (hs[1].bMessageNumber != 2) {
421 dev_err(dev, "Handshake2 failed: bad message number %u\n",
422 hs[1].bMessageNumber);
423 goto error_hs2;
424 }
425 if (hs[1].bStatus != 0) {
426 dev_err(dev, "Handshake2 failed: bad status %u\n",
427 hs[1].bStatus);
428 goto error_hs2;
429 }
430 if (memcmp(hs[0].tTKID, hs[1].tTKID, sizeof(hs[0].tTKID))) {
431 dev_err(dev, "Handshake2 failed: TKID mismatch "
432 "(#1 0x%02x%02x%02x vs #2 0x%02x%02x%02x)\n",
433 hs[0].tTKID[0], hs[0].tTKID[1], hs[0].tTKID[2],
434 hs[1].tTKID[0], hs[1].tTKID[1], hs[1].tTKID[2]);
435 goto error_hs2;
436 }
437 if (memcmp(hs[0].CDID, hs[1].CDID, sizeof(hs[0].CDID))) {
438 dev_err(dev, "Handshake2 failed: CDID mismatch\n");
439 goto error_hs2;
440 }
441
442 /* Setup the CCM nonce */
521aea08 443 memset(&ccm_n.sfn, 0, sizeof(ccm_n.sfn)); /* Per WUSB1.0[6.5.2] */
b6565a07 444 put_unaligned_le32(tkid, ccm_n.tkid);
d59db761
IPG
445 ccm_n.src_addr = wusbhc->uwb_rc->uwb_dev.dev_addr;
446 ccm_n.dest_addr.data[0] = wusb_dev->addr;
447 ccm_n.dest_addr.data[1] = 0;
448
449 /* Derive the KCK and PTK from CK, the CCM, H and D nonces */
450 memcpy(keydvt_in.hnonce, hs[0].nonce, sizeof(keydvt_in.hnonce));
451 memcpy(keydvt_in.dnonce, hs[1].nonce, sizeof(keydvt_in.dnonce));
452 result = wusb_key_derive(&keydvt_out, ck->data, &ccm_n, &keydvt_in);
453 if (result < 0) {
454 dev_err(dev, "Handshake2 failed: cannot derive keys: %d\n",
455 result);
456 goto error_hs2;
457 }
d59db761
IPG
458
459 /* Compute MIC and verify it */
460 result = wusb_oob_mic(mic, keydvt_out.kck, &ccm_n, &hs[1]);
461 if (result < 0) {
462 dev_err(dev, "Handshake2 failed: cannot compute MIC: %d\n",
463 result);
464 goto error_hs2;
465 }
466
d59db761
IPG
467 if (memcmp(hs[1].MIC, mic, sizeof(hs[1].MIC))) {
468 dev_err(dev, "Handshake2 failed: MIC mismatch\n");
469 goto error_hs2;
470 }
471
472 /* Send Handshake3 */
473 hs[2].bMessageNumber = 3;
474 hs[2].bStatus = 0;
b6565a07 475 put_unaligned_le32(tkid, hs[2].tTKID);
d59db761
IPG
476 hs[2].bReserved = 0;
477 memcpy(hs[2].CDID, &wusb_dev->cdid, sizeof(hs[2].CDID));
478 memcpy(hs[2].nonce, hs[0].nonce, sizeof(hs[2].nonce));
479 result = wusb_oob_mic(hs[2].MIC, keydvt_out.kck, &ccm_n, &hs[2]);
480 if (result < 0) {
481 dev_err(dev, "Handshake3 failed: cannot compute MIC: %d\n",
482 result);
483 goto error_hs2;
484 }
485
d59db761
IPG
486 result = usb_control_msg(
487 usb_dev, usb_sndctrlpipe(usb_dev, 0),
488 USB_REQ_SET_HANDSHAKE,
489 USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
7b3e3740 490 3, 0, &hs[2], sizeof(hs[2]), USB_CTRL_SET_TIMEOUT);
d59db761
IPG
491 if (result < 0) {
492 dev_err(dev, "Handshake3: request failed: %d\n", result);
493 goto error_hs3;
494 }
495
d59db761
IPG
496 result = wusbhc->set_ptk(wusbhc, wusb_dev->port_idx, tkid,
497 keydvt_out.ptk, sizeof(keydvt_out.ptk));
498 if (result < 0)
499 goto error_wusbhc_set_ptk;
500
d59db761
IPG
501 result = wusb_dev_set_gtk(wusbhc, wusb_dev);
502 if (result < 0) {
503 dev_err(dev, "Set GTK for device: request failed: %d\n",
504 result);
505 goto error_wusbhc_set_gtk;
506 }
507
508 /* Update the device's address from unauth to auth */
509 if (usb_dev->authenticated == 0) {
d59db761
IPG
510 result = wusb_dev_update_address(wusbhc, wusb_dev);
511 if (result < 0)
512 goto error_dev_update_address;
513 }
514 result = 0;
bce83697 515 dev_info(dev, "device authenticated\n");
d59db761
IPG
516
517error_dev_update_address:
518error_wusbhc_set_gtk:
519error_wusbhc_set_ptk:
520error_hs3:
521error_hs2:
522error_hs1:
523 memset(hs, 0, 3*sizeof(hs[0]));
eb94ec7a
JL
524 memzero_explicit(&keydvt_out, sizeof(keydvt_out));
525 memzero_explicit(&keydvt_in, sizeof(keydvt_in));
526 memzero_explicit(&ccm_n, sizeof(ccm_n));
527 memzero_explicit(mic, sizeof(mic));
bce83697 528 if (result < 0)
d59db761 529 wusb_dev_set_encryption(usb_dev, 0);
d59db761
IPG
530error_dev_set_encryption:
531 kfree(hs);
532error_kzalloc:
533 return result;
534}
535
536/*
537 * Once all connected and authenticated devices have received the new
538 * GTK, switch the host to using it.
539 */
471e42ad 540static void wusbhc_gtk_rekey_work(struct work_struct *work)
d59db761 541{
471e42ad
TP
542 struct wusbhc *wusbhc = container_of(work,
543 struct wusbhc, gtk_rekey_work);
d59db761 544 size_t key_size = sizeof(wusbhc->gtk.data);
471e42ad
TP
545 int port_idx;
546 struct wusb_dev *wusb_dev, *wusb_dev_next;
547 LIST_HEAD(rekey_list);
d59db761
IPG
548
549 mutex_lock(&wusbhc->mutex);
471e42ad
TP
550 /* generate the new key */
551 wusbhc_generate_gtk(wusbhc);
552 /* roll the gtk index. */
553 wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1);
554 /*
555 * Save all connected devices on a list while holding wusbhc->mutex and
556 * take a reference to each one. Then submit the set key request to
557 * them after releasing the lock in order to avoid a deadlock.
558 */
559 for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) {
560 wusb_dev = wusbhc->port[port_idx].wusb_dev;
561 if (!wusb_dev || !wusb_dev->usb_dev
562 || !wusb_dev->usb_dev->authenticated)
563 continue;
d59db761 564
471e42ad
TP
565 wusb_dev_get(wusb_dev);
566 list_add_tail(&wusb_dev->rekey_node, &rekey_list);
567 }
d59db761 568 mutex_unlock(&wusbhc->mutex);
d59db761 569
471e42ad
TP
570 /* Submit the rekey requests without holding wusbhc->mutex. */
571 list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list,
572 rekey_node) {
573 list_del_init(&wusb_dev->rekey_node);
521aea08
RB
574 dev_dbg(&wusb_dev->usb_dev->dev,
575 "%s: rekey device at port %d\n",
471e42ad
TP
576 __func__, wusb_dev->port_idx);
577
578 if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) {
521aea08
RB
579 dev_err(&wusb_dev->usb_dev->dev,
580 "%s: rekey device at port %d failed\n",
471e42ad
TP
581 __func__, wusb_dev->port_idx);
582 }
583 wusb_dev_put(wusb_dev);
584 }
d59db761 585
471e42ad
TP
586 /* Switch the host controller to use the new GTK. */
587 mutex_lock(&wusbhc->mutex);
588 wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
589 &wusbhc->gtk.descr.bKeyData, key_size);
590 mutex_unlock(&wusbhc->mutex);
d59db761
IPG
591}
592
593/**
594 * wusbhc_gtk_rekey - generate and distribute a new GTK
595 * @wusbhc: the WUSB host controller
596 *
597 * Generate a new GTK and distribute it to all connected and
598 * authenticated devices. When all devices have the new GTK, the host
599 * starts using it.
600 *
601 * This must be called after every device disconnect (see [WUSB]
602 * section 6.2.11.2).
603 */
604void wusbhc_gtk_rekey(struct wusbhc *wusbhc)
605{
471e42ad
TP
606 /*
607 * We need to submit a URB to the downstream WUSB devices in order to
608 * change the group key. This can't be done while holding the
609 * wusbhc->mutex since that is also taken in the urb_enqueue routine
610 * and will cause a deadlock. Instead, queue a work item to do
611 * it when the lock is not held
612 */
275e517c 613 queue_work(wusbhc->wq_security, &wusbhc->gtk_rekey_work);
d59db761 614}