mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


  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®