From: Oliver Neukum <oneukum@suse.com>
To: nicolas.bouchinet@oss.cyber.gouv.fr,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>,
Kannappan R <r.kannappan@intel.com>,
Sabyrzhan Tasbolatov <snovitoll@gmail.com>,
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>,
Stefan Eichenberger <stefan.eichenberger@toradex.com>,
Thomas Gleixner <tglx@linutronix.de>,
Pawel Laszczak <pawell@cadence.com>, Ma Ke <make_ruc2021@163.com>,
Jeff Johnson <jeff.johnson@oss.qualcomm.com>,
Luc Bonnafoux <luc.bonnafoux@ssi.gouv.fr>,
Luc Bonnafoux <luc.bonnafoux@oss.cyber.gouv.fr>,
Nicolas Bouchinet <nicolas.bouchinet@ssi.gouv.fr>,
linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
Subject: Re: [RFC PATCH 2/4] usb: core: Introduce usb authentication feature
Date: Wed, 25 Jun 2025 11:59:21 +0200 [thread overview]
Message-ID: <e028a659-9535-4cf9-92c1-373f72fae3cf@suse.com> (raw)
In-Reply-To: <20250620-usb_authentication-v1-2-0d92261a5779@ssi.gouv.fr>
On 20.06.25 16:27, nicolas.bouchinet@oss.cyber.gouv.fr wrote:
> +/**
> + * usb_authent_req_digest - Check if device is known via its digest
> + * @dev: [in] pointer to the usb device to query
> + * @buffer: [inout] buffer to hold request data
> + * @digest: [out] device digest
> + *
> + * Context: task context, might sleep.
> + *
> + * This function sends a digest request to the usb device.
> + *
> + * Possible errors:
> + * - ECOMM : failed to send or received a message to the device
> + * - EINVAL : if buffer or mask is NULL
> + *
> + * Return: If successful, zero. Otherwise, a negative error number.
> + */
> +static int usb_authent_req_digest(struct usb_device *dev, uint8_t *const buffer,
How can buffer be const if it is used for output?
[..]
> +struct usb_auth_cert_req {
> + uint16_t offset;
> + uint16_t length;
> +} __packed;
Endianness?
> +/**
> + * usb_authent_read_certificate - Read a device certificate
> + * @dev: [in] pointer to the usb device to query
> + * @buffer: [inout] buffer to hold request data, caller allocated
> + * @slot: [in] certificate chain to be read
> + * @cert_der: [out] buffer to hold received certificate chain
> + * @cert_len: [out] length of received certificate
> + *
> + * Context: task context, might sleep.
> + *
> + * Possible errors:
> + * - EINVAL : NULL pointer or invalid slot value
> + * - ECOMM : failed to send request to device
> + * - ENOMEM : failed to allocate memory for certificate
> + *
> + * Return: If successful, zero. Otherwise, a negative error number.
> + */
> +static int usb_authent_read_certificate(struct usb_device *dev, uint8_t *const buffer,
> + uint8_t slot, uint8_t **cert_der, size_t *cert_len)
> +{
> + uint16_t read_offset = 0;
> + uint16_t read_length = 0;
> + uint8_t chain_part[64] = { 0 };
> +
> + if (unlikely(slot >= 8 || buffer == NULL || cert_der == NULL || cert_len == NULL)) {
> + pr_err("invalid arguments\n");
> + return -EINVAL;
> + }
> +
> + // First request to get certificate chain length
> + if (usb_auth_read_cert_part(dev, buffer, slot, 0,
> + USB_AUTH_CHAIN_HEADER_SIZE,
> + chain_part) != 0) {
> + pr_err("Failed to get first certificate part\n");
> + return -ECOMM;
> + }
> +
> + // Extract total length
> + *cert_len = ((uint16_t *)chain_part)[0];
Endianness
> +
> +/**
> + * usb_authent_challenge_dev - Challenge a device
> + * @dev: [in] pointer to the usb device to query
> + * @buffer: [in] pointer to the buffer allocated for USB query
> + * @slot: [in] certificate chain to be used
> + * @slot_mask: [in] slot mask of the device
> + * @nonce: [in] nonce to use for the challenge, 32 bytes long
> + * @chall: [out] buffer for chall response, 204 bytes long, caller allocated
> + *
> + * Context: task context, might sleep.
> + *
> + * Possible errors:
> + * - EINVAL : NULL input pointer or invalid slot value
> + * - ECOMM : failed to send or receive message from the device
> + *
> + * Return: If successful, zero. Otherwise, a negative error number.
> + */
> +static int usb_authent_challenge_dev(struct usb_device *dev, uint8_t *buffer,
> + const uint8_t slot, const uint8_t slot_mask, const uint8_t *const nonce,
> + uint8_t *const chall)
> +{
> + int ret = -1;
> +
> + if (unlikely(buffer == NULL || slot >= 8 || nonce == NULL)) {
> + pr_err("invalid arguments\n");
> + return -EINVAL;
> + }
> +
> + // AUTH OUT challenge request transfer
> + memcpy(buffer, nonce, 32);
> + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), AUTH_OUT,
> + USB_DIR_OUT,
> + (USB_SECURITY_PROTOCOL_VERSION << 8) +
> + USB_AUTHENT_CHALLENGE_REQ_TYPE,
> + (slot << 8), buffer, 32, USB_CTRL_GET_TIMEOUT);
> + if (ret < 0) {
> + pr_err("Failed to send challenge request: %d\n", ret);
> + ret = -ECOMM;
> + goto cleanup;
> + }
> +
> + // Complete the challenge with the request
> + chall[1] = USB_SECURITY_PROTOCOL_VERSION;
> + chall[0] = USB_AUTHENT_CHALLENGE_REQ_TYPE;
> + chall[2] = slot;
> + chall[3] = 0x00;
> + memcpy(chall+4, nonce, 32);
This may be worth a definition.
> +
> + // AUTH IN challenge response transfer
> + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), AUTH_IN, USB_DIR_IN,
> + (USB_SECURITY_PROTOCOL_VERSION << 8) +
> + USB_AUTHENT_CHALLENGE_RESP_TYPE,
> + (slot << 8) + slot_mask, buffer, 168,
> + USB_CTRL_GET_TIMEOUT);
> + if (ret < 0) {
> + pr_err("Failed to get challenge response: %d\n", ret);
> + ret = -ECOMM;
> + goto cleanup;
> + }
> +
> + pr_notice("received challenge response\n");
> +
> + // Complete last part of the challenge with what is returned by the device
> + memcpy(chall+USB_AUTH_CHAIN_HEADER_SIZE, buffer, 168);
The 168 comes whence?
> +
> + ret = 0;
> +
> +cleanup:
> +
> + return ret;
> +}
> +/**
> + * @brief Check that the authentication can resume after a sleep
> + *
> + * @param [in] dev : the usb device
> + * @param [in] hub : the parent hub
> + *
> + * Possible error codes:
> + * - ENODEV : hub has been disconnected
> + *
> + * @return 0 if possible to resume, else an error code
> + */
> +static int usb_auth_try_resume(struct usb_device *dev, struct usb_device *hub)
> +{
> + // Test if the hub or the device has been disconnected
> + if (unlikely(hub == NULL || dev == NULL ||
> + dev->port_is_suspended == 1 ||
> + dev->reset_in_progress == 1)) {
> + return -ENODEV;
> + }
> +
> + // TODO: test if the device has not been disconnected
> + // TODO: test if the device has not been disconnected then replaced with another one
> +
> + return 0;
> +}
> +
> +/**
> + * usb_authenticate_device - Challenge a device
> + * @dev: [inout] pointer to device
> + *
> + * Context: task context, might sleep.
> + *
> + * Authentication is done in the following steps:
> + * 1. Get device certificates digest to determine if it is already known
> + * if yes, go to 3.
> + * 2. Get device certificates
> + * 3. Challenge device
> + * 4. Based on previous result, determine if device is allowed under local
> + * security policy.
> + *
> + * Possible error code:
> + * - ENOMEM : failed to allocate memory for exchange
> + * - TODO: complete all possible error case
> + *
> + * Return: If successful, zero. Otherwise, a negative error number.
> + */
> +int usb_authenticate_device(struct usb_device *dev)
> +{
> + int ret = 0;
> +
> + uint8_t is_valid = 0;
> + uint8_t is_known = 0;
> + uint8_t is_blocked = 0;
> + uint8_t chain_nb = 0;
> + uint8_t slot_mask = 0;
> + uint8_t slot = 0;
> + uint8_t digests[256] = { 0 };
> + uint8_t nonce[32] = {0};
> + uint8_t chall[204] = {0};
> + uint32_t dev_id = 0;
> + size_t ctx_size = 0;
> + int i = 0;
> +
> + uint8_t *cert_der = NULL;
> + size_t cert_len = 0;
> +
> + if (unlikely(dev == NULL || dev->parent == NULL))
> + return -ENODEV;
> +
> + struct usb_device *hub = dev->parent;
> +
> + // By default set authorization status at false
> + dev->authorized = 0;
> + dev->authenticated = 0;
> +
> + uint8_t *buffer = NULL;
> + // Buffer to hold responses
> + buffer = kzalloc(512, GFP_KERNEL);
Should this not be cached for comparison after resume?
Regards
Oliver
next prev parent reply other threads:[~2025-06-25 9:59 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-20 14:27 [RFC PATCH 0/4] Support for usb authentication nicolas.bouchinet
2025-06-20 14:27 ` [RFC PATCH 1/4] usb: core: Introduce netlink usb authentication policy engine nicolas.bouchinet
2025-06-21 9:37 ` Sabyrzhan Tasbolatov
2025-06-30 11:42 ` Nicolas Bouchinet
2025-06-20 14:27 ` [RFC PATCH 2/4] usb: core: Introduce usb authentication feature nicolas.bouchinet
2025-06-20 14:54 ` Greg Kroah-Hartman
2025-06-30 11:07 ` Nicolas Bouchinet
2025-06-30 11:43 ` Greg Kroah-Hartman
2025-06-21 10:21 ` Sabyrzhan Tasbolatov
2025-06-30 11:56 ` Nicolas Bouchinet
2025-06-25 9:59 ` Oliver Neukum [this message]
2025-06-30 12:38 ` Nicolas Bouchinet
2025-06-20 14:27 ` [RFC PATCH 3/4] usb: core: Plug the usb authentication capability nicolas.bouchinet
2025-06-20 19:11 ` Alan Stern
2025-06-30 11:20 ` Nicolas Bouchinet
2025-06-30 18:04 ` Alan Stern
2025-06-21 11:09 ` Sabyrzhan Tasbolatov
2025-06-30 12:25 ` Nicolas Bouchinet
2025-06-23 18:15 ` Oliver Neukum
2025-06-30 12:34 ` Nicolas Bouchinet
2025-06-30 13:07 ` Oliver Neukum
2025-06-20 14:27 ` [RFC PATCH 4/4] usb: core: Add Kconfig option to compile usb authorization nicolas.bouchinet
2025-06-21 7:22 ` Greg Kroah-Hartman
2025-06-30 11:22 ` Nicolas Bouchinet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e028a659-9535-4cf9-92c1-373f72fae3cf@suse.com \
--to=oneukum@suse.com \
--cc=gregkh@linuxfoundation.org \
--cc=jeff.johnson@oss.qualcomm.com \
--cc=krzysztof.kozlowski@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=luc.bonnafoux@oss.cyber.gouv.fr \
--cc=luc.bonnafoux@ssi.gouv.fr \
--cc=make_ruc2021@163.com \
--cc=nicolas.bouchinet@oss.cyber.gouv.fr \
--cc=nicolas.bouchinet@ssi.gouv.fr \
--cc=pawell@cadence.com \
--cc=r.kannappan@intel.com \
--cc=snovitoll@gmail.com \
--cc=stefan.eichenberger@toradex.com \
--cc=stern@rowland.harvard.edu \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®