From: Igor Opaniuk <igor.opaniuk@gmail.com>
To: u-boot@lists.u-boot-project.org
Cc: Tom Rini <trini@konsulko.com>,
Mattijs Korpershoek <mkorpershoek@kernel.org>,
Peter Robinson <pbrobinson@gmail.com>,
Quentin Schulz <quentin.schulz@cherry.de>,
Johan Jonker <jbx6244@gmail.com>,
Igor Opaniuk <igor.opaniuk@gmail.com>
Subject: [PATCH 1/4] avb: make the AVB root key source pluggable
Date: Mon, 27 Jul 2026 19:14:13 +0200 [thread overview]
Message-ID: <20260727-avb-root-key-pluggable-v1-1-7e27b2b92cc0@gmail.com> (raw)
In-Reply-To: <20260727-avb-root-key-pluggable-v1-0-7e27b2b92cc0@gmail.com>
AVB's whole chain of trust reduces to a single public key, and that key is
currently hard-coded in U-Boot as the AVB reference/test key, whose private
half is public. That is fine for bring-up but unusable for a locked
product, which must anchor its root of trust in something an attacker
cannot swap out -- a hash fused into the SoC, a secure element -- rather
than a blob compiled into the bootloader.
Make the source of the trusted key digest selectable so a board can decide
where its root of trust lives, without touching the verification logic and
with any lookup failure treated as untrusted. The built-in key remains the
default, so existing users are unaffected; the sources a production device
actually needs are added in the following patches.
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
---
common/Kconfig | 18 ++++++++++++++++++
common/avb_verify.c | 36 +++++++++++++++++++++++++++++++++---
include/avb_verify.h | 19 +++++++++++++++++++
3 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig
index 345be4b8ca1..654e78b7b7a 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -881,6 +881,7 @@ config AVB_VERIFY
depends on MMC
depends on PARTITION_UUIDS
depends on FASTBOOT
+ select SHA256
help
This option enables compilation of bootloader-dependent operations,
used by Android Verified Boot 2.0 library (libavb). Includes:
@@ -904,6 +905,23 @@ config AVB_BUF_SIZE
AVB requires a buffer for memory transactions. This variable defines the
buffer size.
+choice
+ prompt "Source of the trusted AVB root public key"
+ default AVB_ROOT_KEY_BUILTIN
+ help
+ Selects where validate_vbmeta_public_key() obtains the trusted root
+ key digest that the vbmeta signing key is compared against. This is
+ the root of trust for the whole AVB chain.
+
+config AVB_ROOT_KEY_BUILTIN
+ bool "Built-in key hard-coded in avb_verify.c"
+ help
+ Use the avb_root_pub[] blob compiled into U-Boot. By default this is
+ the AVB reference/test key and is intended for development only;
+ replace the blob for production use.
+
+endchoice
+
endif # AVB_VERIFY
config SCP03
diff --git a/common/avb_verify.c b/common/avb_verify.c
index 76c523fd0ba..7c6baa33ed8 100644
--- a/common/avb_verify.c
+++ b/common/avb_verify.c
@@ -11,7 +11,9 @@
#include <part.h>
#include <tee.h>
#include <tee/optee_ta_avb.h>
+#include <u-boot/sha256.h>
+#if CONFIG_IS_ENABLED(AVB_ROOT_KEY_BUILTIN)
static const unsigned char avb_root_pub[1032] = {
0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
0xaf, 0xe3, 0xd3, 0x84, 0x6c, 0x7e, 0xd, 0x89, 0x3d, 0xc2,
@@ -118,6 +120,7 @@ static const unsigned char avb_root_pub[1032] = {
0xe1, 0x74, 0xa1, 0xa3, 0x99, 0xa0, 0x85, 0x9e, 0xf1, 0xac,
0xd8, 0x7e,
};
+#endif /* AVB_ROOT_KEY_BUILTIN */
const char *str_avb_io_error(AvbIOResult res)
{
@@ -654,14 +657,26 @@ static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
public_key_metadata_length,
bool *out_key_is_trusted)
{
+ u8 key_digest[SHA256_SUM_LEN];
+ u8 trusted_digest[SHA256_SUM_LEN];
+ AvbIOResult rc;
+
if (!public_key_length || !public_key_data || !out_key_is_trusted)
return AVB_IO_RESULT_ERROR_IO;
+ /* Default deny: only flip to trusted on a positive digest match. */
*out_key_is_trusted = false;
- if (public_key_length != sizeof(avb_root_pub))
- return AVB_IO_RESULT_ERROR_IO;
- if (memcmp(avb_root_pub, public_key_data, public_key_length) == 0)
+ /* Digest of the key embedded in the (untrusted) vbmeta. */
+ sha256_csum_wd(public_key_data, public_key_length, key_digest,
+ CHUNKSZ_SHA256);
+
+ /* Digest of the trusted root key from the configured source. */
+ rc = avb_read_root_key_digest(ops, trusted_digest);
+ if (rc != AVB_IO_RESULT_OK)
+ return rc;
+
+ if (avb_safe_memcmp(key_digest, trusted_digest, sizeof(key_digest)) == 0)
*out_key_is_trusted = true;
return AVB_IO_RESULT_OK;
@@ -1040,6 +1055,21 @@ free_name:
}
#endif
+/**
+ * ============================================================================
+ * AVB root key digest providers (selected via CONFIG_AVB_ROOT_KEY_*)
+ * ============================================================================
+ */
+#if CONFIG_IS_ENABLED(AVB_ROOT_KEY_BUILTIN)
+AvbIOResult avb_read_root_key_digest(AvbOps *ops, uint8_t *digest)
+{
+ sha256_csum_wd(avb_root_pub, sizeof(avb_root_pub), digest,
+ CHUNKSZ_SHA256);
+
+ return AVB_IO_RESULT_OK;
+}
+#endif
+
/**
* ============================================================================
* AVB2.0 AvbOps alloc/initialisation/free
diff --git a/include/avb_verify.h b/include/avb_verify.h
index 5d998b5a302..66655aab871 100644
--- a/include/avb_verify.h
+++ b/include/avb_verify.h
@@ -47,6 +47,25 @@ enum mmc_io_type {
AvbOps *avb_ops_alloc(int boot_device);
void avb_ops_free(AvbOps *ops);
+/**
+ * avb_read_root_key_digest() - get the SHA-256 digest of the trusted AVB
+ * root public key
+ *
+ * This is the root of trust for AVB: validate_vbmeta_public_key() hashes the
+ * key embedded in the (untrusted) vbmeta and compares it against the digest
+ * returned here. The provider is selected via CONFIG_AVB_ROOT_KEY_* and, for
+ * CONFIG_AVB_ROOT_KEY_BOARD, may be overridden by a SoC/board specific strong
+ * definition (e.g. reading a hash fused into OTP).
+ *
+ * @ops: AvbOps, contains AVB ops handlers (needed by the TEE provider)
+ * @digest: output buffer of AVB_SHA256_DIGEST_SIZE bytes
+ *
+ * @return:
+ * AVB_IO_RESULT_OK on success (@digest populated)
+ * any other AvbIOResult fails verification closed (key not trusted)
+ */
+AvbIOResult avb_read_root_key_digest(AvbOps *ops, uint8_t *digest);
+
char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state);
char *avb_set_enforce_verity(const char *cmdline);
char *avb_set_ignore_corruption(const char *cmdline);
--
2.53.0
next prev parent reply other threads:[~2026-07-27 17:14 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 17:14 [PATCH 0/4] avb: make the AVB root key source pluggable Igor Opaniuk
2026-07-27 17:14 ` Igor Opaniuk [this message]
2026-08-10 9:41 ` [PATCH 1/4] " Mattijs Korpershoek
2026-07-27 17:14 ` [PATCH 2/4] avb: add OP-TEE root key digest provider Igor Opaniuk
2026-08-10 9:43 ` Mattijs Korpershoek
2026-07-27 17:14 ` [PATCH 3/4] avb: add board-specific root key provider Igor Opaniuk
2026-08-10 9:44 ` Mattijs Korpershoek
2026-07-27 17:14 ` [PATCH 4/4] doc: android: document the AVB root key source Igor Opaniuk
2026-08-10 9:46 ` Mattijs Korpershoek
2026-08-12 7:44 ` [PATCH 0/4] avb: make the AVB root key source pluggable Mattijs Korpershoek
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=20260727-avb-root-key-pluggable-v1-1-7e27b2b92cc0@gmail.com \
--to=igor.opaniuk@gmail.com \
--cc=jbx6244@gmail.com \
--cc=mkorpershoek@kernel.org \
--cc=pbrobinson@gmail.com \
--cc=quentin.schulz@cherry.de \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/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