From: Sascha Hauer <s.hauer@pengutronix.de>
To: Jonas Rebmann <jre@pengutronix.de>
Cc: BAREBOX <barebox@lists.infradead.org>,
	Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: Re: [PATCH v2 10/17] common: tlv: Add TLV-Signature support
Date: Mon, 3 Nov 2025 11:02:32 +0100	[thread overview]
Message-ID: <aQh9uBVAHngkoCow@pengutronix.de> (raw)
In-Reply-To: <20251028-tlv-signature-v2-10-3bafce636ad7@pengutronix.de>
On Tue, Oct 28, 2025 at 07:03:15PM +0100, Jonas Rebmann wrote:
> Implement TLV signature using the existing placeholders for it. Use the
> existing cryptographic primitives and public key handling used for
> fitimage verification.
> 
> Signature is verified and then must be valid iff CONFIG_TLV_SIGNATURE is
> enabled and a keyring is selected for the decoder. SHA256 hashing is
> hardcoded for now.
> 
> As 16 bit are well sufficient to store the length of the signature
> section in bytes, reduce it to its least significant 16 bit and reserve
> the remaining 16 bit for future use.
> 
> As sig_len where the only reserved bits left, and where zero-reserved,
> this leaves more wiggle room to still expand the format in the future.
> 
> Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
> ---
>  common/Kconfig       |  5 +++
>  common/tlv/parser.c  | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/tlv/format.h | 22 ++++++++++---
>  3 files changed, 109 insertions(+), 5 deletions(-)
> 
> diff --git a/common/Kconfig b/common/Kconfig
> index d923d4c4b6..663465443d 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -1122,6 +1122,11 @@ config TLV
>  	  barebox TLV is a scheme for storing factory data on non-volatile
>  	  storage. Unlike state, it's meant to be read-only.
>  
> +config TLV_SIGNATURE
> +	bool "barebox TLV signature support"
> +	depends on TLV
> +	select CRYPTO_BUILTIN_KEYS
> +
>  config TLV_DRV
>  	bool "barebox TLV generic driver"
>  	depends on TLV
> diff --git a/common/tlv/parser.c b/common/tlv/parser.c
> index f74ada99d7..cbf45413dd 100644
> --- a/common/tlv/parser.c
> +++ b/common/tlv/parser.c
> @@ -1,6 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0-only
>  
>  #define pr_fmt(fmt) "barebox-tlv: " fmt
> +#include "tlv/format.h"
>  
>  #include <common.h>
>  #include <tlv/tlv.h>
> @@ -9,6 +10,80 @@
>  #include <linux/stat.h>
>  #include <crc.h>
>  #include <net.h>
> +#include <crypto/public_key.h>
> +
> +static int tlv_verify_try_key(const struct public_key *key, const uint8_t *sig,
> +			      const uint32_t sig_len, const void *data,
> +			      unsigned long data_len)
> +{
> +	enum hash_algo algo = HASH_ALGO_SHA256;
> +	int ret;
> +	struct digest *digest;
> +	void *hash;
> +
> +	digest = digest_alloc_by_algo(algo);
> +	if (!digest)
> +		return -ENOMEM;
> +
> +	digest_init(digest);
> +	if (IS_ERR(digest)) {
What you meant to do here is
	ret = digest_init(digest);
	if (ret) {
		...
	}
> +		digest_free(digest);
> +		return -EINVAL;
> +	}
> +	digest_update(digest, data, data_len);
> +	hash = xzalloc(digest_length(digest));
> +	digest_final(digest, hash);
> +
> +	ret = public_key_verify(key, sig, sig_len, hash, algo);
> +
> +	digest_free(digest);
> +	free(hash);
> +
> +	return ret;
> +}
> +
> +static int tlv_verify(struct tlv_header *header, const char *keyring)
> +{
> +	const struct public_key *key;
> +	size_t payload_sz = tlv_spki_hash_offset(header);
> +	const void *spki_tlv_ptr = (void *)header + payload_sz;
> +	u32 spki_tlv = get_unaligned_le32(spki_tlv_ptr);
> +	int SPKI_LEN = 4;
> +	u32 sig_len = get_unaligned_be16(&header->length_sig);
> +	int ret, id;
> +	int count_spki_matches = 0;
> +
> +	if (!IS_ENABLED(CONFIG_TLV_SIGNATURE)) {
> +		pr_err("signature selected in decoder but not enabled!\n");
> +		return -ENOSYS;
> +	} else if (sig_len == 0) {
> +		pr_err("signature selected in decoder but an unsigned TLV matched by magic %08x!\n", be32_to_cpu(header->magic));
> +		return -EPROTO;
> +	}
> +	/* signature length field must always be zeroed during signing and verification */
> +	header->length_sig = 0;
> +
> +	for_each_public_key_keyring(key, id, keyring) {
> +		u32 spki_key = get_unaligned_le32(key->hash);
> +
> +		if (spki_key == spki_tlv) {
> +			count_spki_matches++;
> +			ret = tlv_verify_try_key(key, spki_tlv_ptr + SPKI_LEN, sig_len - SPKI_LEN, header, payload_sz);
> +			if (!ret)
> +				return 0;
> +			pr_warn("TLV spki %08x matched available key but signature verification failed: %pe!\n", spki_tlv, ERR_PTR(ret));
Not sure what this warning is about. Either it can happen that there are
two keys with the same hash in which case there's nothing to warn about,
or it can't happen and you would return an error here.
> +		}
> +	}
> +
> +	/* reset signature length field after verification to avoid later confusion */
> +	put_unaligned_be16(sig_len, &header->length_sig);
You do not write the original value back when tlv_verify_try_key()
succeeds.
It might be less confusing if you treat the original header const and
duplicate it in tlv_verify_try_key().
> +
> +	if (!count_spki_matches) {
> +		pr_warn("TLV spki %08x matched no key!\n", spki_tlv);
> +		return -ENOKEY;
> +	}
> +	return -EINVAL;
> +}
>  
>  int tlv_parse(struct tlv_device *tlvdev,
>  	      const struct tlv_decoder *decoder)
> @@ -17,6 +92,7 @@ int tlv_parse(struct tlv_device *tlvdev,
>  	struct tlv_mapping *map = NULL;
>  	struct tlv_header *header = tlv_device_header(tlvdev);
>  	u32 magic;
> +	u16 reserved;
>  	size_t size;
>  	int ret = 0;
>  	u32 crc = ~0;
> @@ -24,6 +100,7 @@ int tlv_parse(struct tlv_device *tlvdev,
>  	magic = be32_to_cpu(header->magic);
>  
>  	size = tlv_total_len(header);
> +	reserved = get_unaligned_be16(&header->reserved);
>  
>  	if (size == SIZE_MAX) {
>  		pr_warn("Invalid TLV header, overflows\n");
> @@ -36,6 +113,16 @@ int tlv_parse(struct tlv_device *tlvdev,
>  		return -EILSEQ;
>  	}
>  
> +	if (decoder->signature_keyring) {
> +		ret = tlv_verify(header, decoder->signature_keyring);
> +		if (ret)
> +			return ret;
Does this mean I can bypass the verification just by putting some
unsigned TLV data with TLV_MAGIC_BAREBOX_V1 into the TLV partition?
Sascha
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
next prev parent reply	other threads:[~2025-11-03 10:03 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-28 18:03 [PATCH v2 00/17] TLV-Signature and keyrings Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 01/17] lib: idr: avoid dangling else in idr_for_each_entry() Jonas Rebmann
2025-11-03 10:11   ` Ahmad Fatoum
2025-10-28 18:03 ` [PATCH v2 02/17] common: clean up TLV code Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 03/17] crypto: Add support for keyrings Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 04/17] fit: only accept keys from "fit"-keyring Jonas Rebmann
2025-11-03  9:04   ` Sascha Hauer
2025-10-28 18:03 ` [PATCH v2 05/17] crypto: keytoc: Rename "hint" to "fit-hint" and do not use it in identifiers Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 06/17] commands: keys: update output format to include keyring Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 07/17] commands: tlv: Error out on invalid TLVs Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 08/17] scripts: bareboxtlv-generator: Implement signature Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 09/17] scripts: bareboxtlv-generator: Increase max_size in example schema Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 10/17] common: tlv: Add TLV-Signature support Jonas Rebmann
2025-11-03 10:02   ` Sascha Hauer [this message]
2025-11-03 11:21     ` Jonas Rebmann
2025-11-03 11:41       ` Sascha Hauer
2025-11-03 11:55         ` Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 11/17] common: tlv: default decoder for signed TLV Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 12/17] crypto: Use "development" keys for "fit" and "tlv" keyring Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 13/17] test: py: add signature to TLV integration tests Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 14/17] ci: pytest: Add kconfig fragment for TLV signature " Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 15/17] crypto: concatenate fit development certificate with private key Jonas Rebmann
2025-11-03 10:08   ` Sascha Hauer
2025-11-03 11:41     ` Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 16/17] doc/barebox-tlv: Update documentation regarding TLV-Signature Jonas Rebmann
2025-10-28 18:03 ` [PATCH v2 17/17] Documentation: migration-2025.11.0: List changes to CONFIG_CRYPTO_PUBLIC_KEYS Jonas Rebmann
2025-11-03 10:16   ` Sascha Hauer
2025-11-03 10:26     ` Ahmad Fatoum
2025-11-03 10:41       ` Sascha Hauer
2025-11-03 10:45         ` Ahmad Fatoum
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=aQh9uBVAHngkoCow@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=jre@pengutronix.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