
From: Stephen Carlson stcarlso@linux.microsoft.com
New config CONFIG_ARBP to enable enforcement of OS anti-rollback counter during image loading.
Images with an anti-rollback counter value "arbvn" declared in the FDT will be compared against the current device anti-rollback counter value, and older images will not pass signature validation. If the image is newer, the device anti-rollback counter value will be updated.
Signed-off-by: Stephen Carlson stcarlso@linux.microsoft.com --- boot/Kconfig | 9 +++++ boot/image-fit-sig.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ boot/image-fit.c | 23 ++++++++++++ include/image.h | 4 ++ 4 files changed, 125 insertions(+)
diff --git a/boot/Kconfig b/boot/Kconfig index e8fb03b801..e08c274b7c 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -103,6 +103,15 @@ config FIT_CIPHER Enable the feature of data ciphering/unciphering in the tool mkimage and in the u-boot support of the FIT image.
+config FIT_ARBP + bool "Enable Anti rollback version check for FIT images" + depends on FIT_SIGNATURE + default n + help + Enables FIT image anti-rollback protection. This feature is required + when a platform needs to retire previous versions of FIT images due to + security flaws and prevent devices from being reverted to them. + config FIT_VERBOSE bool "Show verbose messages when FIT images fail" depends on FIT diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c index 12369896fe..bf3b81a3a3 100644 --- a/boot/image-fit-sig.c +++ b/boot/image-fit-sig.c @@ -11,6 +11,8 @@ #include <log.h> #include <malloc.h> #include <asm/global_data.h> +#include <dm.h> +#include <dm-security.h> DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <fdt_region.h> @@ -63,6 +65,39 @@ struct image_region *fit_region_make_list(const void *fit, return region; }
+#if !defined(USE_HOSTCC) +static int fit_image_verify_arbvn(const void *fit, int image_noffset) +{ + u64 image_arbvn; + u64 plat_arbvn = 0ULL; + struct udevice *dev; + int ret; + + ret = fit_image_get_arbvn(fit, image_noffset, &image_arbvn); + if (ret) + return 0; + + ret = uclass_first_device_err(UCLASS_SECURITY, &dev); + if (ret) + return -ENODEV; + + ret = dm_security_arbvn_get(dev, &plat_arbvn); + if (ret) + return -EIO; + + if (image_arbvn < plat_arbvn) { + return -EPERM; + } else if (image_arbvn > plat_arbvn) { + ret = dm_security_arbvn_set(dev, image_arbvn); + printf(" Updating OS anti-rollback to %llu from %llu\n", + image_arbvn, plat_arbvn); + return ret; + } + + return 0; +} +#endif + static int fit_image_setup_verify(struct image_sign_info *info, const void *fit, int noffset, const void *key_blob, int required_keynode, @@ -175,6 +210,16 @@ static int fit_image_verify_sig(const void *fit, int image_noffset, goto error; }
+#if !defined(USE_HOSTCC) + if (FIT_IMAGE_ENABLE_ARBP && verified) { + ret = fit_image_verify_arbvn(fit, image_noffset); + if (ret) { + err_msg = "Anti-rollback verification failed"; + goto error; + } + } +#endif + return verified ? 0 : -EPERM;
error: @@ -385,6 +430,40 @@ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, return 0; }
+#if !defined(USE_HOSTCC) +static int fit_config_verify_arbvn(const void *fit, int conf_noffset, + int sig_offset) +{ + static const char default_list[] = FIT_KERNEL_PROP "\0" + FIT_FDT_PROP; + int ret, len; + const char *prop, *iname, *end; + int image_noffset; + + /* If there is "sign-images" property, use that */ + prop = fdt_getprop(fit, sig_offset, "sign-images", &len); + if (!prop) { + prop = default_list; + len = sizeof(default_list); + } + + /* Locate the images */ + end = prop + len; + for (iname = prop; iname < end; iname += strlen(iname) + 1) { + image_noffset = fit_conf_get_prop_node(fit, conf_noffset, + iname, IH_PHASE_NONE); + if (image_noffset < 0) + return -ENOENT; + + ret = fit_image_verify_arbvn(fit, image_noffset); + if (ret) + return ret; + } + + return 0; +} +#endif + /** * fit_config_verify_key() - Verify that a configuration is signed with a key * @@ -444,6 +523,16 @@ static int fit_config_verify_key(const void *fit, int conf_noffset, goto error; }
+#if !defined(USE_HOSTCC) + if (FIT_IMAGE_ENABLE_ARBP && verified) { + ret = fit_config_verify_arbvn(fit, conf_noffset, noffset); + if (ret) { + err_msg = "Anti-rollback verification failed"; + goto error; + } + } +#endif + if (verified) return 0;
diff --git a/boot/image-fit.c b/boot/image-fit.c index 3cc556b727..d4e324752a 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1084,6 +1084,29 @@ int fit_image_get_data_and_size(const void *fit, int noffset, return ret; }
+/** + * fit_image_get_arbvn - get anti-rollback counter + * @fit: pointer to the FIT image header + * @noffset: component image node offset + * @arbvn: holds the arbvn property value + * + * returns: + * 0, on success + * -ENOENT if the property could not be found + */ +int fit_image_get_arbvn(const void *fit, int noffset, uint64_t *arbvn) +{ + const fdt64_t *val; + + val = fdt_getprop(fit, noffset, FIT_ARBVN_PROP, NULL); + if (!val) + return -ENOENT; + + *arbvn = fdt64_to_cpu(*val); + + return 0; +} + /** * fit_image_hash_get_algo - get hash algorithm name * @fit: pointer to the FIT format image header diff --git a/include/image.h b/include/image.h index 01a6787d21..497772fb4b 100644 --- a/include/image.h +++ b/include/image.h @@ -1024,6 +1024,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size, #define FIT_COMP_PROP "compression" #define FIT_ENTRY_PROP "entry" #define FIT_LOAD_PROP "load" +#define FIT_ARBVN_PROP "arbvn"
/* configuration node */ #define FIT_KERNEL_PROP "kernel" @@ -1105,6 +1106,7 @@ int fit_image_get_data_size_unciphered(const void *fit, int noffset, size_t *data_size); int fit_image_get_data_and_size(const void *fit, int noffset, const void **data, size_t *size); +int fit_image_get_arbvn(const void *fit, int noffset, uint64_t *arbvn);
/** * fit_get_data_node() - Get verified image data for an image @@ -1389,6 +1391,7 @@ int calculate_hash(const void *data, int data_len, const char *algo, * device */ #if defined(USE_HOSTCC) +# define FIT_IMAGE_ENABLE_ARBP 0 # if defined(CONFIG_FIT_SIGNATURE) # define IMAGE_ENABLE_SIGN 1 # define FIT_IMAGE_ENABLE_VERIFY 1 @@ -1400,6 +1403,7 @@ int calculate_hash(const void *data, int data_len, const char *algo, #else # define IMAGE_ENABLE_SIGN 0 # define FIT_IMAGE_ENABLE_VERIFY CONFIG_IS_ENABLED(FIT_SIGNATURE) +# define FIT_IMAGE_ENABLE_ARBP CONFIG_IS_ENABLED(FIT_ARBP) #endif
#ifdef USE_HOSTCC