[RFC PATCH v2 0/4] Support for usb authentication

nicolas.bouchinet@oss.cyber.gouv.fr posted 4 patches 2 months, 3 weeks ago
Documentation/usb/authentication.rst      |   15 +
Documentation/usb/index.rst               |    1 +
drivers/usb/core/Kconfig                  |   26 +
drivers/usb/core/Makefile                 |    5 +
drivers/usb/core/authent.c                |  586 ++++++++++++++++
drivers/usb/core/authent.h                |  192 ++++++
drivers/usb/core/authent_netlink.c        | 1039 +++++++++++++++++++++++++++++
drivers/usb/core/authent_netlink.h        |   33 +
drivers/usb/core/config.c                 |   22 +-
drivers/usb/core/driver.c                 |   31 +
drivers/usb/core/hub.c                    |    5 +
drivers/usb/core/sysctl.c                 |   55 ++
drivers/usb/core/sysfs.c                  |   16 +
drivers/usb/core/usb.c                    |   16 +
include/linux/usb.h                       |   11 +
include/uapi/linux/usb/usb_auth_netlink.h |   70 ++
16 files changed, 2121 insertions(+), 2 deletions(-)
[RFC PATCH v2 0/4] Support for usb authentication
Posted by nicolas.bouchinet@oss.cyber.gouv.fr 2 months, 3 weeks ago
We have been working on the implementation of the USB authentication
protocol in the kernel.

You can find our work here https://github.com/ANSSI-FR/usb_authentication.

It is still work in progress but we would like to start discussions
about the implementation design and its possible integration to the
Linux kernel.

Best regards,

Nicolas and Luc

---
USB peripheral authentication
=============================

USB peripherals are an important attack vector in personal computers and
pose a risk to the cyber security of companies and organizations.

The USB foundation has published a standard to allow the authentication
of USB peripherals ([1] and [2]). It defines a mechanism for the host to
request credentials and issue an authentication challenge to USB-2 or
USB-3 peripherals, either upon connection or later during the use of the
peripheral.

We currently envision the following use cases for USB authentication:

- company networks where computers and peripherals can be privately
  controlled and administered;
- USB cleaning or decontamination stations;
- individuals who want to prevent unauthorized device plug-in into their
  machine.

The implementation of this feature will obviously necessitate efforts
from both the kernel community and peripherals vendors. We believe that
providing an implementation of the host side of the protocol in the
Linux kernel will encourage constructors to include this feature in
their devices. On the other hand, we are working on implementing
reference code for embedded devices, notably for Zephyr OS.

Design
======

The USB authentication protocol is based on a simple signature
challenge. Devices hold between 1 and 8 pairs of private signing key and
x509 certificate. Hosts must possess a store of root Certificate
Authority certificates provided by device vendors.

The protocol exchange is driven by the host and can be decomposed into
three, mostly independent, phases:

- The Host can request a digest of each certificate owned by the
  peripheral.
- If the Host does not recognize the peripheral from one of its digests,
  it can read one or more certificates from the device until a valid one
  is found.
- The Host can issue an authentication challenge to the peripheral.

On the host side, this requires the following functions:

- handling the protocol exchange with the peripheral;
- X509 certificates validation and administration (root CA loading,
  certificate revocation…);
- cryptographic functions for the challenge (random number generation
  and ECDSA with the NIST P256 -secp256r1- curve);
- security policy management;
- authorization decision enforcement.

We chose to implement the authentication protocol exchange directly in
the kernel USB stack during the device enumeration. This is done by
first requesting the device BOS to detect its capacity at handling
authentication, then if supported starting the authentication sequence
with a digest request.

The implementation of the other functions is open to several design
alternatives, mainly based on their distribution between kernel and user
space. In this first implementation, we chose to implement most (all) of
the cryptographic functions, certificate management and security policy
management in user space in order to limit impact on the kernel side.
This allows for more personalization later on. The communication between
the kernel USB stack authentication function and user space is done via
a generic netlink socket.

Once a device has been authenticated, a per-device authenticated field
is update with the result of the authentication. The authenticated field
can be used to track the result of the authentication process in
userspace thanks to a sysfs exposed file.

The device enforcement point is done in the usb_probe_interface()
function. This allows for more complex security policy in userspace: the
user could manually authorize a device that failed the authentication or
manually deauthorize a device that was previously authenticated.

+----------+------------+-------------+
|          | authorized | !authorized |
+----------+------------+-------------+
| authent  |     OK     |     NOK     |
+----------+------------+-------------+
| !authent |     OK     |     NOK     |
+----------+------------+-------------+

If set to true, the authentication decision is enforced, the following
decision is made:

+----------+------------+-------------+
|          | authorized | !authorized |
+----------+------------+-------------+
| authent  |     OK     |     NOK     |
+----------+------------+-------------+
| !authent |    NOK     |     NOK     |
+----------+------------+-------------+

Note that combined with the CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=2:
 - internal devices should be authorized and !authenticated => OK
 - external qemu dev-auth is !authorized and authenticated  => NOK at
   first but then authorization can be granted via sysfs.
 - external qemu non auth dev is !authorized and !authenticated => NOK
   and authorization can be granted via sysfs

The default enforcement decision can be configured thanks to the new
USB_AUTHENTICATION_ENFORCE configuration option and can be overridden
using the usbcore.enforce_authentication command line or module
parameter.

Limitations
===========

The USB authentication protocol come with some inherent limitations, [3]
does a good job at describing most of them. During the implementation,
we also found that the value encoding of the Validity field in the x509
certificate differs from the RFC5280 [4]. This has prevented us from
using the x509 parser included in the Linux kernel or OpenSSL, we chose
to use the mbedtls library instead [5]. This obviously does not prevent
others to replace it with their preferred implementation. It will also
open discussions on the protocol enhancement.

The architectural choice to place most of the cryptographic and security
management functions in user space comes with its own limitations.

First it introduces a dependency on the user space program availability.
It will probably be necessary to introduce a fail-safe mechanism if the
authentication can not be completed. Also, during early boot stages the
user space service will be needed in one form or another in the
initramfs.

The second limitation is that the device initialization process is
paused multiple times. Each time, the hub lock is released in order not
to block the rest of the stack; and then reacquired when a response has
been received from user space. The resuming of the operation on the
device must be done with great care.

Last, we do not yet interface properly with the rest of the usb stack
and thus do not enforce a strict control of the two authenticated and
authorized fields. Other sections of the kernel or userspace are able to
overwrite those fields using the sysfs exposed files for example.

Status
======

The current kernel implementation of the USB authentication protocol is
experimental and has the following limitations:

- It does not yet handle all possible protocol errors.
- It has been tested with a QEMU mock device, but tests with real
  hardware are still in progress. As such, the over-the-wire protocol
  has not yet been fully validated.
- The kernel/user space communication has not yet been completely
  validated, including the interruption of the worker thread and its
  resuming.
- Device authorization and deauthorization has not been completely
  implemented.
- It lacks an overall documentation and test suite.

Upstreaming plans
=================

Our current kernel patch is obviously a work-in-progress and not yet
ready for merging. We feel it is best to start a discussion on the
architectural choices and gather early comments that could be used to
improve the design.

Concerning the user space functions, they are currently implemented in a
small independent executable as a proof-of-concept. In the future,
integrating it in existing larger projects, like USBGuard [6], would
allow presenting a homogeneous USB administration interface to the user.

Reviewing this RFC
==================

We would like to get comments on the proposed architectural choices
regarding the repartition of functions between kernel and user space and
on the implementation in the USB stack, mostly concerning the releasing
and reacquiring the hub lock multiple times during the authentication
process.

Testing this RFC
================

You can find in the following repository [7] the necessary code for
creating a test environment:

- the Linux kernel patches;
- a python utility to generate a small PKI for device enrollment;
- a C minimalist service to implement the USB policy engine;
- patches for QEMU to implement a mock USB device with the
  authentication capability;
- a testbed to compile and test the project.

References
==========

- [1] “Universal Serial Bus Security Foundation Specification”, Revision
  1.0 with ECN and Errata through January 7, 2019
- [2] “Universal Serial Bus Type-C Authentication Specification”,
  Revision 1.0 with ECN and Errata through January 7, 2019
- [3] J. Tian, N. Scaife, D. Kumar, M. Bailey, A. Bates and K. Butler,
  "SoK: "Plug & Pray" Today – Understanding USB Insecurity in Versions 1
  Through C," 2018 IEEE Symposium on Security and Privacy (SP), San
  Francisco, CA, USA, 2018, pp. 1032-1047, doi: 10.1109/SP.2018.00037
- [4] RFC 5280, Internet X.509 Public Key Infrastructure Certificate and
  Certificate Revocation List (CRL) Profile, May 2008
- [5] https://www.trustedfirmware.org/projects/mbed-tls/
- [6] https://usbguard.github.io/
- [7] https://github.com/ANSSI-FR/usb_authentication

Signed-off-by: Luc Bonnafoux <luc.bonnafoux@ssi.gouv.fr>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Kannappan R <r.kannappan@intel.com>
Cc: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Stefan Eichenberger <stefan.eichenberger@toradex.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Pawel Laszczak <pawell@cadence.com>
Cc: Ma Ke <make_ruc2021@163.com>
Cc: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Cc: Luc Bonnafoux <luc.bonnafoux@ssi.gouv.fr>
Cc: Luc Bonnafoux <luc.bonnafoux@oss.cyber.gouv.fr>
Cc: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>
Cc: linux-kernel@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Signed-off-by: Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>

---
Changes in v2:
- Fix code documentation to match kernel-doc format
- General coding style fixes as suggested in v1
- Added netlink socket configuration checks when receiving messages from
  userspace.
- Moved usb_authenticate_device() after device enumeration
- Changed the way authentication enforcement is handled.
  - If the device is authenticated, the device authenticated field is
    set to 1.
  - Added an authenticated file in sysfs that reflects the device
    authenticated field.
  - Enforcement Kconfig and cmdline configurations has been added.
  - Sysctls has been added to permit timeouts values.
- Removed USBAUTH_CMD_RESP_REMOVE_DEV netlink command
- The Kconfig commit has been squashed in the commit that plugs of the
  authentication in the usb stack.
- Link to v1: https://lore.kernel.org/r/20250620-usb_authentication-v1-0-0d92261a5779@ssi.gouv.fr

---
Nicolas Bouchinet (4):
      usb: core: Introduce netlink usb authentication policy engine
      usb: core: Introduce usb authentication feature
      usb: core: Plug the usb authentication capability
      usb: core: Add sysctl to configure authentication timeouts

 Documentation/usb/authentication.rst      |   15 +
 Documentation/usb/index.rst               |    1 +
 drivers/usb/core/Kconfig                  |   26 +
 drivers/usb/core/Makefile                 |    5 +
 drivers/usb/core/authent.c                |  586 ++++++++++++++++
 drivers/usb/core/authent.h                |  192 ++++++
 drivers/usb/core/authent_netlink.c        | 1039 +++++++++++++++++++++++++++++
 drivers/usb/core/authent_netlink.h        |   33 +
 drivers/usb/core/config.c                 |   22 +-
 drivers/usb/core/driver.c                 |   31 +
 drivers/usb/core/hub.c                    |    5 +
 drivers/usb/core/sysctl.c                 |   55 ++
 drivers/usb/core/sysfs.c                  |   16 +
 drivers/usb/core/usb.c                    |   16 +
 include/linux/usb.h                       |   11 +
 include/uapi/linux/usb/usb_auth_netlink.h |   70 ++
 16 files changed, 2121 insertions(+), 2 deletions(-)
---
base-commit: fc85704c3dae5ac1cb3c94045727241cd72871ff
change-id: 20250620-usb_authentication-333bda6f33fe

Best regards,
-- 
Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>

Re: [RFC PATCH v2 0/4] Support for usb authentication
Posted by Greg Kroah-Hartman 2 months, 3 weeks ago
On Fri, Jul 11, 2025 at 10:41:21AM +0200, nicolas.bouchinet@oss.cyber.gouv.fr wrote:
> We have been working on the implementation of the USB authentication
> protocol in the kernel.
> 
> You can find our work here https://github.com/ANSSI-FR/usb_authentication.
> 
> It is still work in progress but we would like to start discussions
> about the implementation design and its possible integration to the
> Linux kernel.
> 
> Best regards,
> 
> Nicolas and Luc
> 
> ---
> USB peripheral authentication
> =============================
> 
> USB peripherals are an important attack vector in personal computers and
> pose a risk to the cyber security of companies and organizations.
> 
> The USB foundation has published a standard to allow the authentication
> of USB peripherals ([1] and [2]). It defines a mechanism for the host to
> request credentials and issue an authentication challenge to USB-2 or
> USB-3 peripherals, either upon connection or later during the use of the
> peripheral.
> 
> We currently envision the following use cases for USB authentication:
> 
> - company networks where computers and peripherals can be privately
>   controlled and administered;
> - USB cleaning or decontamination stations;
> - individuals who want to prevent unauthorized device plug-in into their
>   machine.
> 
> The implementation of this feature will obviously necessitate efforts
> from both the kernel community and peripherals vendors. We believe that
> providing an implementation of the host side of the protocol in the
> Linux kernel will encourage constructors to include this feature in
> their devices. On the other hand, we are working on implementing
> reference code for embedded devices, notably for Zephyr OS.
> 
> Design
> ======
> 
> The USB authentication protocol is based on a simple signature
> challenge. Devices hold between 1 and 8 pairs of private signing key and
> x509 certificate. Hosts must possess a store of root Certificate
> Authority certificates provided by device vendors.

Who is going to distribute these host keys?  Who is going to be
responsible for revocations and the like?

> The protocol exchange is driven by the host and can be decomposed into
> three, mostly independent, phases:
> 
> - The Host can request a digest of each certificate owned by the
>   peripheral.
> - If the Host does not recognize the peripheral from one of its digests,
>   it can read one or more certificates from the device until a valid one
>   is found.
> - The Host can issue an authentication challenge to the peripheral.

Is this the same type of protocol that PCI has implemented for its use
of "trusted devices"?  If so, why not emulate what the kernel patches
for PCI do here as well to keep one common kernel/userspace api?  If
not, what are the major differences?

> On the host side, this requires the following functions:
> 
> - handling the protocol exchange with the peripheral;
> - X509 certificates validation and administration (root CA loading,
>   certificate revocation…);

Is the validation going to be done by the kernel?  Userspace?  And how?
Is a chain-of-trust defined somewhere?

> - cryptographic functions for the challenge (random number generation
>   and ECDSA with the NIST P256 -secp256r1- curve);
> - security policy management;
> - authorization decision enforcement.
> 
> We chose to implement the authentication protocol exchange directly in
> the kernel USB stack during the device enumeration. This is done by
> first requesting the device BOS to detect its capacity at handling
> authentication, then if supported starting the authentication sequence
> with a digest request.
> 
> The implementation of the other functions is open to several design
> alternatives, mainly based on their distribution between kernel and user
> space. In this first implementation, we chose to implement most (all) of
> the cryptographic functions, certificate management and security policy
> management in user space in order to limit impact on the kernel side.
> This allows for more personalization later on. The communication between
> the kernel USB stack authentication function and user space is done via
> a generic netlink socket.

Again, is this what PCI has decided to do?  Surely they didn't implement
a different way of authenticating devices, did they?  (I can dream...)

> Once a device has been authenticated, a per-device authenticated field
> is update with the result of the authentication. The authenticated field
> can be used to track the result of the authentication process in
> userspace thanks to a sysfs exposed file.

This is _VERY_ close to what the old wireless USB protocol required,
right?  And I think you've tied into much the same places we did for
that protocol, but you might want to look into the past history for when
we removed that to be sure.

> The device enforcement point is done in the usb_probe_interface()
> function. This allows for more complex security policy in userspace: the
> user could manually authorize a device that failed the authentication or
> manually deauthorize a device that was previously authenticated.
> 
> +----------+------------+-------------+
> |          | authorized | !authorized |
> +----------+------------+-------------+
> | authent  |     OK     |     NOK     |
> +----------+------------+-------------+
> | !authent |     OK     |     NOK     |
> +----------+------------+-------------+

What is "NOK"?  And what are the two axis?  The sysfs file values?  Or
an internal variable?

> If set to true, the authentication decision is enforced, the following
> decision is made:

If what is "set to true"?

> +----------+------------+-------------+
> |          | authorized | !authorized |
> +----------+------------+-------------+
> | authent  |     OK     |     NOK     |
> +----------+------------+-------------+
> | !authent |    NOK     |     NOK     |
> +----------+------------+-------------+
> 
> Note that combined with the CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=2:

What does "2" mean?

>  - internal devices should be authorized and !authenticated => OK
>  - external qemu dev-auth is !authorized and authenticated  => NOK at
>    first but then authorization can be granted via sysfs.
>  - external qemu non auth dev is !authorized and !authenticated => NOK
>    and authorization can be granted via sysfs

Wait, what does qemu have to do with anything here?

And this is getting to be a complex set of interactions, testing the
combinations is going to be rough without regression tests...

> The default enforcement decision can be configured thanks to the new
> USB_AUTHENTICATION_ENFORCE configuration option and can be overridden
> using the usbcore.enforce_authentication command line or module
> parameter.
> 
> Limitations
> ===========
> 
> The USB authentication protocol come with some inherent limitations, [3]

That's a 2018 reference!  Are you saying that the newly designed
protocol was already discussed in 2018 and found lacking?

> does a good job at describing most of them. During the implementation,
> we also found that the value encoding of the Validity field in the x509
> certificate differs from the RFC5280 [4].

Can this be fixed?

> This has prevented us from
> using the x509 parser included in the Linux kernel or OpenSSL, we chose
> to use the mbedtls library instead [5].

Ugh, why?  Why not fix up the kernel parser to work with this broken
implementation instead?  How is any other operating system handling this
if the implementation is broken?  How was it ever tested?

> This obviously does not prevent
> others to replace it with their preferred implementation. It will also
> open discussions on the protocol enhancement.

Have you done this with the usb-if?

Note, Linux was explicitly kicked out of particapating in usb-if
discussions in the past by some of the core members a decade or so ago
because they did not want us to implement specifications before other
operating systems had the chance to.  So, given that this is a new spec,
has Windows added support for this yet to prove it actually can work?

What's the odds that usb-if is willing to talk to us again?  :)

> The architectural choice to place most of the cryptographic and security
> management functions in user space comes with its own limitations.
> 
> First it introduces a dependency on the user space program availability.
> It will probably be necessary to introduce a fail-safe mechanism if the
> authentication can not be completed. Also, during early boot stages the
> user space service will be needed in one form or another in the
> initramfs.

Ugh, that's going to get messy fast, so putting this in the kernel might
be the simplest way if at all possible.  At least for "boot devices", or
just punt and don't care about USB devices at boot time?

> The second limitation is that the device initialization process is
> paused multiple times. Each time, the hub lock is released in order not
> to block the rest of the stack; and then reacquired when a response has
> been received from user space. The resuming of the operation on the
> device must be done with great care.

USB probe sequences are slow based on the slow devices, so I doubt this
is going to even be noticable.  Have you seen any real slow-down in your
testing?

> Last, we do not yet interface properly with the rest of the usb stack
> and thus do not enforce a strict control of the two authenticated and
> authorized fields. Other sections of the kernel or userspace are able to
> overwrite those fields using the sysfs exposed files for example.

Why would the kernel be writing these values?  And if userspace isn't
supposed to be writing to these anymore, just change the permissions on
the sysfs files, OR just fail the write with the logic in the kernel
itself.

> Status
> ======
> 
> The current kernel implementation of the USB authentication protocol is
> experimental and has the following limitations:
> 
> - It does not yet handle all possible protocol errors.
> - It has been tested with a QEMU mock device, but tests with real
>   hardware are still in progress. As such, the over-the-wire protocol
>   has not yet been fully validated.

Are there any real devices out there?  Is there a test-device from
usb-if that we can use?  Surely usb-if published some example code to
prove that the specification works before ratification happened, right?

> - The kernel/user space communication has not yet been completely
>   validated, including the interruption of the worker thread and its
>   resuming.

What worker thread?  The hub?

> - Device authorization and deauthorization has not been completely
>   implemented.
> - It lacks an overall documentation and test suite.

testing is going to be key here :)

> Upstreaming plans
> =================
> 
> Our current kernel patch is obviously a work-in-progress and not yet
> ready for merging. We feel it is best to start a discussion on the
> architectural choices and gather early comments that could be used to
> improve the design.
> 
> Concerning the user space functions, they are currently implemented in a
> small independent executable as a proof-of-concept. In the future,
> integrating it in existing larger projects, like USBGuard [6], would
> allow presenting a homogeneous USB administration interface to the user.

Yes, usbguard interaction would be good as that's what Linux userspace
has standardized on.  Have you looked into that yet?

> Reviewing this RFC
> ==================
> 
> We would like to get comments on the proposed architectural choices
> regarding the repartition of functions between kernel and user space and
> on the implementation in the USB stack, mostly concerning the releasing
> and reacquiring the hub lock multiple times during the authentication
> process.
> 
> Testing this RFC
> ================
> 
> You can find in the following repository [7] the necessary code for
> creating a test environment:
> 
> - the Linux kernel patches;
> - a python utility to generate a small PKI for device enrollment;
> - a C minimalist service to implement the USB policy engine;
> - patches for QEMU to implement a mock USB device with the
>   authentication capability;
> - a testbed to compile and test the project.

As mentioned before, a usb gadget patch might be simpler than dealing
with qemu, right?

thanks,

greg k-h
Re: [RFC PATCH v2 0/4] Support for usb authentication
Posted by Nicolas Bouchinet 2 months, 2 weeks ago
On Sun, Jul 13, 2025 at 05:25:03PM +0200, Greg Kroah-Hartman wrote:
> On Fri, Jul 11, 2025 at 10:41:21AM +0200, nicolas.bouchinet@oss.cyber.gouv.fr wrote:
> > We have been working on the implementation of the USB authentication
> > protocol in the kernel.
> > 
> > You can find our work here https://github.com/ANSSI-FR/usb_authentication.
> > 
> > It is still work in progress but we would like to start discussions
> > about the implementation design and its possible integration to the
> > Linux kernel.
> > 
> > Best regards,
> > 
> > Nicolas and Luc
> > 
> > ---
> > USB peripheral authentication
> > =============================
> > 
> > USB peripherals are an important attack vector in personal computers and
> > pose a risk to the cyber security of companies and organizations.
> > 
> > The USB foundation has published a standard to allow the authentication
> > of USB peripherals ([1] and [2]). It defines a mechanism for the host to
> > request credentials and issue an authentication challenge to USB-2 or
> > USB-3 peripherals, either upon connection or later during the use of the
> > peripheral.
> > 
> > We currently envision the following use cases for USB authentication:
> > 
> > - company networks where computers and peripherals can be privately
> >   controlled and administered;
> > - USB cleaning or decontamination stations;
> > - individuals who want to prevent unauthorized device plug-in into their
> >   machine.
> > 
> > The implementation of this feature will obviously necessitate efforts
> > from both the kernel community and peripherals vendors. We believe that
> > providing an implementation of the host side of the protocol in the
> > Linux kernel will encourage constructors to include this feature in
> > their devices. On the other hand, we are working on implementing
> > reference code for embedded devices, notably for Zephyr OS.
> > 
> > Design
> > ======
> > 
> > The USB authentication protocol is based on a simple signature
> > challenge. Devices hold between 1 and 8 pairs of private signing key and
> > x509 certificate. Hosts must possess a store of root Certificate
> > Authority certificates provided by device vendors.
> 
> Who is going to distribute these host keys?  Who is going to be
> responsible for revocations and the like?
> 
The the first 4 slots must be used by certificate authenticated with
USB-IF root CA. The last 4 slots can be used freely by usb device
vendors or system administrators. It will be the role of the userspace
policy engine to allow the configuration of the trusted root CAs and the
revocation lists.
We are currently on the mind that its out of scope of this kernel
patchset.

> > The protocol exchange is driven by the host and can be decomposed into
> > three, mostly independent, phases:
> > 
> > - The Host can request a digest of each certificate owned by the
> >   peripheral.
> > - If the Host does not recognize the peripheral from one of its digests,
> >   it can read one or more certificates from the device until a valid one
> >   is found.
> > - The Host can issue an authentication challenge to the peripheral.
> 
> Is this the same type of protocol that PCI has implemented for its use
> of "trusted devices"?  If so, why not emulate what the kernel patches
> for PCI do here as well to keep one common kernel/userspace api?  If
> not, what are the major differences?
> 
Currently, as far as we can see in the kernel code, trust for PCI
devices is solely based on whether they are placed on a external facing
PCI port marked as untrusted or not. It is similar to the concept of
internal devices for USB. But in both cases it does not involve any
cryptographic authentication of the device.

We however have been recently aware of the effort to port the SPDM
protocol for PCI in the kernel [1]. We think it could be a great
opportunitie to study if its possible to join our efforts. @Lukas,
@Alistair.

[1]: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/

> > On the host side, this requires the following functions:
> > 
> > - handling the protocol exchange with the peripheral;
> > - X509 certificates validation and administration (root CA loading,
> >   certificate revocation…);
> 
> Is the validation going to be done by the kernel?  Userspace?  And how?
> Is a chain-of-trust defined somewhere?
> 
As said below, we think its best to left the complexity of the
certificates validation to the userspace.

> > - cryptographic functions for the challenge (random number generation
> >   and ECDSA with the NIST P256 -secp256r1- curve);
> > - security policy management;
> > - authorization decision enforcement.
> > 
> > We chose to implement the authentication protocol exchange directly in
> > the kernel USB stack during the device enumeration. This is done by
> > first requesting the device BOS to detect its capacity at handling
> > authentication, then if supported starting the authentication sequence
> > with a digest request.
> > 
> > The implementation of the other functions is open to several design
> > alternatives, mainly based on their distribution between kernel and user
> > space. In this first implementation, we chose to implement most (all) of
> > the cryptographic functions, certificate management and security policy
> > management in user space in order to limit impact on the kernel side.
> > This allows for more personalization later on. The communication between
> > the kernel USB stack authentication function and user space is done via
> > a generic netlink socket.
> 
> Again, is this what PCI has decided to do?  Surely they didn't implement
> a different way of authenticating devices, did they?  (I can dream...)
> 
We are not completely sure yet if the SPDM protocol is compatible with
the USB authentication.

> > Once a device has been authenticated, a per-device authenticated field
> > is update with the result of the authentication. The authenticated field
> > can be used to track the result of the authentication process in
> > userspace thanks to a sysfs exposed file.
> 
> This is _VERY_ close to what the old wireless USB protocol required,
> right?  And I think you've tied into much the same places we did for
> that protocol, but you might want to look into the past history for when
> we removed that to be sure.
> 
We will do some git archeology. Thanks for the hint.

> > The device enforcement point is done in the usb_probe_interface()
> > function. This allows for more complex security policy in userspace: the
> > user could manually authorize a device that failed the authentication or
> > manually deauthorize a device that was previously authenticated.
> > 
> > +----------+------------+-------------+
> > |          | authorized | !authorized |
> > +----------+------------+-------------+
> > | authent  |     OK     |     NOK     |
> > +----------+------------+-------------+
> > | !authent |     OK     |     NOK     |
> > +----------+------------+-------------+
> 
> What is "NOK"?  And what are the two axis?  The sysfs file values?  Or
> an internal variable?
> 
NOK means Not OK. Authorized and authenticated represent the two
bitfields in the usb_device struct. They are reflected in the sysfs in
their respective files.

> > If set to true, the authentication decision is enforced, the following
> > decision is made:
> 
> If what is "set to true"?
> 
Sorry for that, we meant if the new `USB_AUTHENTICATION_ENFORCE` kernel
parameter is set to true.

> > +----------+------------+-------------+
> > |          | authorized | !authorized |
> > +----------+------------+-------------+
> > | authent  |     OK     |     NOK     |
> > +----------+------------+-------------+
> > | !authent |    NOK     |     NOK     |
> > +----------+------------+-------------+
> > 
> > Note that combined with the CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=2:
> 
> What does "2" mean?
> 
We are refering to the usb authorized_default mode that authorizes by
default internal devices only. The idea here is that, paired with
`USB_AUTHENTICATION_ENFORCE` we can more finely control the enforcement
point.

> >  - internal devices should be authorized and !authenticated => OK
> >  - external qemu dev-auth is !authorized and authenticated  => NOK at
> >    first but then authorization can be granted via sysfs.
> >  - external qemu non auth dev is !authorized and !authenticated => NOK
> >    and authorization can be granted via sysfs
> 
> Wait, what does qemu have to do with anything here?
> 
> And this is getting to be a complex set of interactions, testing the
> combinations is going to be rough without regression tests...
> 
Sorry for that, we were refering to our current test device implemented
in qemu. But was supposed to be any external usb devices.

> > The default enforcement decision can be configured thanks to the new
> > USB_AUTHENTICATION_ENFORCE configuration option and can be overridden
> > using the usbcore.enforce_authentication command line or module
> > parameter.
> > 
> > Limitations
> > ===========
> > 
> > The USB authentication protocol come with some inherent limitations, [3]
> 
> That's a 2018 reference!  Are you saying that the newly designed
> protocol was already discussed in 2018 and found lacking?
> 
As far as we are aware, the last version of the specification [1] is the
last is the last version that includes errata from 2019. [3] is a
research paper that explored the limitation of the protocol. We are not
aware of any evolution since. We saw that SPDM reuses some of the USB
specification fields but we are not entirely sure yet if can be used in
place of the USB specification and if it fixes the limitations.

> > does a good job at describing most of them. During the implementation,
> > we also found that the value encoding of the Validity field in the x509
> > certificate differs from the RFC5280 [4].
> 
> Can this be fixed?
> 
> > This has prevented us from
> > using the x509 parser included in the Linux kernel or OpenSSL, we chose
> > to use the mbedtls library instead [5].
> 
> Ugh, why?  Why not fix up the kernel parser to work with this broken
> implementation instead?  How is any other operating system handling this
> if the implementation is broken?  How was it ever tested?
> 
We think its up to the USB-IF to fix their specification and not up to
the kernel to adapt its behavior.

> > This obviously does not prevent
> > others to replace it with their preferred implementation. It will also
> > open discussions on the protocol enhancement.
> 
> Have you done this with the usb-if?
> 
 We have not yet contacted the USB-IF to report those issues.

> Note, Linux was explicitly kicked out of particapating in usb-if
> discussions in the past by some of the core members a decade or so ago
> because they did not want us to implement specifications before other
> operating systems had the chance to.  So, given that this is a new spec,
> has Windows added support for this yet to prove it actually can work?
> 
> What's the odds that usb-if is willing to talk to us again?  :)
> 
> > The architectural choice to place most of the cryptographic and security
> > management functions in user space comes with its own limitations.
> > 
> > First it introduces a dependency on the user space program availability.
> > It will probably be necessary to introduce a fail-safe mechanism if the
> > authentication can not be completed. Also, during early boot stages the
> > user space service will be needed in one form or another in the
> > initramfs.
> 
> Ugh, that's going to get messy fast, so putting this in the kernel might
> be the simplest way if at all possible.  At least for "boot devices", or
> just punt and don't care about USB devices at boot time?
> 
As we see it we could indeed do everything in the kernel but it will
mean that either every vendor certificates have to be loaded at compile
time as well as the security policy. Or we would need a way to load the
policy and certificates later through sysfs for example.

For the former it would be pretty unflexible. For the later as far as we
understand it there needs to be an userspace available and thus it is
possible to have an userspace policy engine.

> > The second limitation is that the device initialization process is
> > paused multiple times. Each time, the hub lock is released in order not
> > to block the rest of the stack; and then reacquired when a response has
> > been received from user space. The resuming of the operation on the
> > device must be done with great care.
> 
> USB probe sequences are slow based on the slow devices, so I doubt this
> is going to even be noticable.  Have you seen any real slow-down in your
> testing?
> 
We have not seen any slowdown, our concern is that the usb_device struct
pointer is no longer valid if for example the device has been ejected
during the authentication sequence. We still need to harden our current
implementation.

> > Last, we do not yet interface properly with the rest of the usb stack
> > and thus do not enforce a strict control of the two authenticated and
> > authorized fields. Other sections of the kernel or userspace are able to
> > overwrite those fields using the sysfs exposed files for example.
> 
> Why would the kernel be writing these values?  And if userspace isn't
> supposed to be writing to these anymore, just change the permissions on
> the sysfs files, OR just fail the write with the logic in the kernel
> itself.
> 
Since the second patchset, we have been working on the enforcement of
the two authenticated and authorized bitfields. The authenticated sysfs
file is exposed as read-only.

> > Status
> > ======
> > 
> > The current kernel implementation of the USB authentication protocol is
> > experimental and has the following limitations:
> > 
> > - It does not yet handle all possible protocol errors.
> > - It has been tested with a QEMU mock device, but tests with real
> >   hardware are still in progress. As such, the over-the-wire protocol
> >   has not yet been fully validated.
> 
> Are there any real devices out there?  Is there a test-device from
> usb-if that we can use?  Surely usb-if published some example code to
> prove that the specification works before ratification happened, right?
> 
Not yet but we hope that having a host implementation will encourage the
vendors to publish authenticated devices.

> > - The kernel/user space communication has not yet been completely
> >   validated, including the interruption of the worker thread and its
> >   resuming.
> 
> What worker thread?  The hub?
> 
Yes, the hub one.

> > - Device authorization and deauthorization has not been completely
> >   implemented.
> > - It lacks an overall documentation and test suite.
> 
> testing is going to be key here :)
> 
Agreed.

> > Upstreaming plans
> > =================
> > 
> > Our current kernel patch is obviously a work-in-progress and not yet
> > ready for merging. We feel it is best to start a discussion on the
> > architectural choices and gather early comments that could be used to
> > improve the design.
> > 
> > Concerning the user space functions, they are currently implemented in a
> > small independent executable as a proof-of-concept. In the future,
> > integrating it in existing larger projects, like USBGuard [6], would
> > allow presenting a homogeneous USB administration interface to the user.
> 
> Yes, usbguard interaction would be good as that's what Linux userspace
> has standardized on.  Have you looked into that yet?
> 
Yes but we chose to implement our minimal test userspace policy engine
for now. We will happily look into it later.

> > Reviewing this RFC
> > ==================
> > 
> > We would like to get comments on the proposed architectural choices
> > regarding the repartition of functions between kernel and user space and
> > on the implementation in the USB stack, mostly concerning the releasing
> > and reacquiring the hub lock multiple times during the authentication
> > process.
> > 
> > Testing this RFC
> > ================
> > 
> > You can find in the following repository [7] the necessary code for
> > creating a test environment:
> > 
> > - the Linux kernel patches;
> > - a python utility to generate a small PKI for device enrollment;
> > - a C minimalist service to implement the USB policy engine;
> > - patches for QEMU to implement a mock USB device with the
> >   authentication capability;
> > - a testbed to compile and test the project.
> 
> As mentioned before, a usb gadget patch might be simpler than dealing
> with qemu, right?
> 
It's feasible, for our current use we think it is easier to test with
qemu and virtme-ng. We currently use the testbed we published [7].

If it were to be implemented in a Linux gadget, it will raise the
question of a secure storage for the authentication key.

Thanks,

Nicolas and Luc
Re: [RFC PATCH v2 0/4] Support for usb authentication
Posted by Greg Kroah-Hartman 2 months, 1 week ago
Hi,

Let me focus right now on only one thing here:

On Mon, Jul 21, 2025 at 04:51:52PM +0200, Nicolas Bouchinet wrote:
> > > Limitations
> > > ===========
> > > 
> > > The USB authentication protocol come with some inherent limitations, [3]
> > 
> > That's a 2018 reference!  Are you saying that the newly designed
> > protocol was already discussed in 2018 and found lacking?
> > 
> As far as we are aware, the last version of the specification [1] is the
> last is the last version that includes errata from 2019. [3] is a
> research paper that explored the limitation of the protocol. We are not
> aware of any evolution since. We saw that SPDM reuses some of the USB
> specification fields but we are not entirely sure yet if can be used in
> place of the USB specification and if it fixes the limitations.

So, this spec has been out since 2019, and it's "broken", AND there are
no actual devices using this?

If there is no hardware out there, I really do not want to be adding new
features to the kernel for this.  We ripped out wireless usb because the
thing never actually shipped and was dropped by the vendors.  Let's not
do that again here.

So if there is no hardware, there's no need for this at all, right?
Where are the vendors that wrote this spec, and why did they not
actually add support for this to their devices already?

And, most importantly, is Windows going to support this?  Because if it
is not, then there is no need for us to support it either as no vendor
is going to only be building a USB device just for Linux systems, right?

So, where are the vendors?  Without that, this is not going to actually
go very far at all, and just bit-rot in our tree :(

thanks,

greg k-h
Re: [RFC PATCH v2 0/4] Support for usb authentication
Posted by Greg Kroah-Hartman 2 months, 3 weeks ago
On Fri, Jul 11, 2025 at 10:41:21AM +0200, nicolas.bouchinet@oss.cyber.gouv.fr wrote:
> We have been working on the implementation of the USB authentication
> protocol in the kernel.
> 
> You can find our work here https://github.com/ANSSI-FR/usb_authentication.
> 
> It is still work in progress but we would like to start discussions
> about the implementation design and its possible integration to the
> Linux kernel.
> 
> Best regards,
> 
> Nicolas and Luc
> 
> ---
> USB peripheral authentication
> =============================
> 
> USB peripherals are an important attack vector in personal computers and
> pose a risk to the cyber security of companies and organizations.
> 
> The USB foundation has published a standard to allow the authentication
> of USB peripherals ([1] and [2]). It defines a mechanism for the host to
> request credentials and issue an authentication challenge to USB-2 or
> USB-3 peripherals, either upon connection or later during the use of the
> peripheral.
> 
> We currently envision the following use cases for USB authentication:
> 
> - company networks where computers and peripherals can be privately
>   controlled and administered;
> - USB cleaning or decontamination stations;
> - individuals who want to prevent unauthorized device plug-in into their
>   machine.
> 
> The implementation of this feature will obviously necessitate efforts
> from both the kernel community and peripherals vendors. We believe that
> providing an implementation of the host side of the protocol in the
> Linux kernel will encourage constructors to include this feature in
> their devices. On the other hand, we are working on implementing
> reference code for embedded devices, notably for Zephyr OS.

What about Linux as a device (i.e. the USB gadget system?)

If we have support for that here, then we can test both sides at the
same time on the same machine, making all of this much easier to
validate it works.  Have you considered doing that work first instead of
doing it in zephyr in a totally different source tree where it makes it
very hard, if not impossible, for us to test this code ourselves?

thanks,

greg k-h