diff mbox series

[u-boot,v2019.04-aspeed-openbmc,2/6] image: Control FIT uImage signature verification at runtime

Message ID 20220131012538.73021-3-andrew@aj.id.au
State New
Headers show
Series Runtime control of vboot via GPIO | expand

Commit Message

Andrew Jeffery Jan. 31, 2022, 1:25 a.m. UTC
Some platform designs include support for disabling secure-boot via a
jumper on the board. Sometimes this control can be separate from the
mechanism enabling the root-of-trust for the platform. Add support for
this latter scenario by allowing boards to implement
board_fit_image_require_verfied(), which is then invoked in the usual
FIT verification paths.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
 Kconfig            |  9 +++++++++
 common/image-fit.c | 17 +++++++++++++++--
 include/image.h    |  9 +++++++++
 3 files changed, 33 insertions(+), 2 deletions(-)

Comments

Eddie James Feb. 3, 2022, 5:22 p.m. UTC | #1
On 1/30/22 19:25, Andrew Jeffery wrote:
> Some platform designs include support for disabling secure-boot via a
> jumper on the board. Sometimes this control can be separate from the
> mechanism enabling the root-of-trust for the platform. Add support for
> this latter scenario by allowing boards to implement
> board_fit_image_require_verfied(), which is then invoked in the usual
> FIT verification paths.


Reviewed-by: Eddie James <eajames@linux.ibm.com


>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> ---
>   Kconfig            |  9 +++++++++
>   common/image-fit.c | 17 +++++++++++++++--
>   include/image.h    |  9 +++++++++
>   3 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/Kconfig b/Kconfig
> index c3dfa8de47c8..11f796035ae4 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -322,6 +322,15 @@ config FIT_SIGNATURE
>   	  format support in this case, enable it using
>   	  CONFIG_IMAGE_FORMAT_LEGACY.
>   
> +if FIT_SIGNATURE
> +config FIT_RUNTIME_SIGNATURE
> +	bool "Control verification of FIT uImages at runtime"
> +	help
> +	  This option allows board support to disable verification of
> +	  signatures at runtime, for example through the state of a GPIO.
> +endif # FIT_SIGNATURE
> +
> +
>   config FIT_SIGNATURE_MAX_SIZE
>   	hex "Max size of signed FIT structures"
>   	depends on FIT_SIGNATURE
> diff --git a/common/image-fit.c b/common/image-fit.c
> index 3c8667f93de2..eb1e66b02b68 100644
> --- a/common/image-fit.c
> +++ b/common/image-fit.c
> @@ -1199,6 +1199,14 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
>   	return 0;
>   }
>   
> +#ifndef __weak
> +#define __weak
> +#endif
> +__weak int board_fit_image_require_verified(void)
> +{
> +	return 1;
> +}
> +
>   int fit_image_verify_with_data(const void *fit, int image_noffset,
>   			       const void *data, size_t size)
>   {
> @@ -1209,6 +1217,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>   
>   	/* Verify all required signatures */
>   	if (IMAGE_ENABLE_VERIFY &&
> +	    fit_image_require_verified() &&
>   	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
>   					   gd_fdt_blob(), &verify_all)) {
>   		err_msg = "Unable to verify required signature";
> @@ -1230,7 +1239,9 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>   						 &err_msg))
>   				goto error;
>   			puts("+ ");
> -		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
> +		} else if (IMAGE_ENABLE_VERIFY &&
> +				fit_image_require_verified() &&
> +				verify_all &&
>   				!strncmp(name, FIT_SIG_NODENAME,
>   					strlen(FIT_SIG_NODENAME))) {
>   			ret = fit_image_check_sig(fit, noffset, data,
> @@ -1849,7 +1860,9 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
>   		if (image_type == IH_TYPE_KERNEL)
>   			images->fit_uname_cfg = fit_base_uname_config;
>   
> -		if (IMAGE_ENABLE_VERIFY && images->verify) {
> +		if (IMAGE_ENABLE_VERIFY &&
> +				fit_image_require_verified() &&
> +				images->verify) {
>   			puts("   Verifying Hash Integrity ... ");
>   			if (fit_config_verify(fit, cfg_noffset)) {
>   				puts("Bad Data Hash\n");
> diff --git a/include/image.h b/include/image.h
> index 937c7eee8ffb..19ea743af08f 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -1103,6 +1103,15 @@ int calculate_hash(const void *data, int data_len, const char *algo,
>   # define IMAGE_ENABLE_VERIFY	0
>   #endif
>   
> +/*
> + * Further, allow run-time control of verification, e.g. via a jumper
> + */
> +#if defined(CONFIG_FIT_RUNTIME_SIGNATURE)
> +# define fit_image_require_verified()	board_fit_image_require_verified()
> +#else
> +# define fit_image_require_verified()	IMAGE_ENABLE_VERIFY
> +#endif
> +
>   #ifdef USE_HOSTCC
>   void *image_get_host_blob(void);
>   void image_set_host_blob(void *host_blob);
Joel Stanley Feb. 8, 2022, 6:03 a.m. UTC | #2
On Mon, 31 Jan 2022 at 01:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>
> Some platform designs include support for disabling secure-boot via a
> jumper on the board. Sometimes this control can be separate from the
> mechanism enabling the root-of-trust for the platform. Add support for
> this latter scenario by allowing boards to implement
> board_fit_image_require_verfied(), which is then invoked in the usual
> FIT verification paths.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> ---
>  Kconfig            |  9 +++++++++
>  common/image-fit.c | 17 +++++++++++++++--
>  include/image.h    |  9 +++++++++
>  3 files changed, 33 insertions(+), 2 deletions(-)
>
> diff --git a/Kconfig b/Kconfig
> index c3dfa8de47c8..11f796035ae4 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -322,6 +322,15 @@ config FIT_SIGNATURE
>           format support in this case, enable it using
>           CONFIG_IMAGE_FORMAT_LEGACY.
>
> +if FIT_SIGNATURE
> +config FIT_RUNTIME_SIGNATURE
> +       bool "Control verification of FIT uImages at runtime"

Can you follow the pattern of the other FIT_ options by making this
depends on FIT_SIGNATURE?

> +       help
> +         This option allows board support to disable verification of
> +         signatures at runtime, for example through the state of a GPIO.
> +endif # FIT_SIGNATURE
> +
> +
>  config FIT_SIGNATURE_MAX_SIZE
>         hex "Max size of signed FIT structures"
>         depends on FIT_SIGNATURE
> diff --git a/common/image-fit.c b/common/image-fit.c
> index 3c8667f93de2..eb1e66b02b68 100644
> --- a/common/image-fit.c
> +++ b/common/image-fit.c
> @@ -1199,6 +1199,14 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
>         return 0;
>  }
>
> +#ifndef __weak
> +#define __weak
> +#endif

Shouldn't we always get this from linux/compiler.h?

> +__weak int board_fit_image_require_verified(void)
> +{
> +       return 1;
> +}
> +
>  int fit_image_verify_with_data(const void *fit, int image_noffset,
>                                const void *data, size_t size)
>  {
> @@ -1209,6 +1217,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>
>         /* Verify all required signatures */
>         if (IMAGE_ENABLE_VERIFY &&
> +           fit_image_require_verified() &&
>             fit_image_verify_required_sigs(fit, image_noffset, data, size,
>                                            gd_fdt_blob(), &verify_all)) {
>                 err_msg = "Unable to verify required signature";
> @@ -1230,7 +1239,9 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>                                                  &err_msg))
>                                 goto error;
>                         puts("+ ");
> -               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
> +               } else if (IMAGE_ENABLE_VERIFY &&
> +                               fit_image_require_verified() &&
> +                               verify_all &&

reading through this it's quite confusing.

We have IMAGE_ENABLE_VERIFY, a compile time constant that will be true
if CONFIG_FIT_SIGNATURE is enabled.

We're adding a function that will override this.

So we could have a function:

__weak bool fit_enable_verification(void)
{
   return IMAGE_ENABLE_VERIFY;
}

The downside of this would be if a board were to implement this but
not have FIT_SIGNATURE enabled then they could return true when they
shouldn't. You could go back to this:

static bool fit_enable_verification(void)
{
   return IMAGE_ENABLE_VERIFY && board_fit_image_require_verified();
}

And drop the ifdefs from image.h

>                                 !strncmp(name, FIT_SIG_NODENAME,
>                                         strlen(FIT_SIG_NODENAME))) {
>                         ret = fit_image_check_sig(fit, noffset, data,
> @@ -1849,7 +1860,9 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
>                 if (image_type == IH_TYPE_KERNEL)
>                         images->fit_uname_cfg = fit_base_uname_config;
>
> -               if (IMAGE_ENABLE_VERIFY && images->verify) {
> +               if (IMAGE_ENABLE_VERIFY &&
> +                               fit_image_require_verified() &&
> +                               images->verify) {
>                         puts("   Verifying Hash Integrity ... ");
>                         if (fit_config_verify(fit, cfg_noffset)) {
>                                 puts("Bad Data Hash\n");
> diff --git a/include/image.h b/include/image.h
> index 937c7eee8ffb..19ea743af08f 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -1103,6 +1103,15 @@ int calculate_hash(const void *data, int data_len, const char *algo,
>  # define IMAGE_ENABLE_VERIFY   0
>  #endif
>
> +/*
> + * Further, allow run-time control of verification, e.g. via a jumper
> + */
> +#if defined(CONFIG_FIT_RUNTIME_SIGNATURE)
> +# define fit_image_require_verified()  board_fit_image_require_verified()
> +#else
> +# define fit_image_require_verified()  IMAGE_ENABLE_VERIFY
> +#endif
> +
>  #ifdef USE_HOSTCC
>  void *image_get_host_blob(void);
>  void image_set_host_blob(void *host_blob);
> --
> 2.32.0
>
Andrew Jeffery Feb. 8, 2022, 9:58 p.m. UTC | #3
On Tue, 8 Feb 2022, at 16:33, Joel Stanley wrote:
> On Mon, 31 Jan 2022 at 01:26, Andrew Jeffery <andrew@aj.id.au> wrote:
>>
>> Some platform designs include support for disabling secure-boot via a
>> jumper on the board. Sometimes this control can be separate from the
>> mechanism enabling the root-of-trust for the platform. Add support for
>> this latter scenario by allowing boards to implement
>> board_fit_image_require_verfied(), which is then invoked in the usual
>> FIT verification paths.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> ---
>>  Kconfig            |  9 +++++++++
>>  common/image-fit.c | 17 +++++++++++++++--
>>  include/image.h    |  9 +++++++++
>>  3 files changed, 33 insertions(+), 2 deletions(-)
>>
>> diff --git a/Kconfig b/Kconfig
>> index c3dfa8de47c8..11f796035ae4 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -322,6 +322,15 @@ config FIT_SIGNATURE
>>           format support in this case, enable it using
>>           CONFIG_IMAGE_FORMAT_LEGACY.
>>
>> +if FIT_SIGNATURE
>> +config FIT_RUNTIME_SIGNATURE
>> +       bool "Control verification of FIT uImages at runtime"
>
> Can you follow the pattern of the other FIT_ options by making this
> depends on FIT_SIGNATURE?

Yeah, I didn't think about this enough :)

>
>> +       help
>> +         This option allows board support to disable verification of
>> +         signatures at runtime, for example through the state of a GPIO.
>> +endif # FIT_SIGNATURE
>> +
>> +
>>  config FIT_SIGNATURE_MAX_SIZE
>>         hex "Max size of signed FIT structures"
>>         depends on FIT_SIGNATURE
>> diff --git a/common/image-fit.c b/common/image-fit.c
>> index 3c8667f93de2..eb1e66b02b68 100644
>> --- a/common/image-fit.c
>> +++ b/common/image-fit.c
>> @@ -1199,6 +1199,14 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
>>         return 0;
>>  }
>>
>> +#ifndef __weak
>> +#define __weak
>> +#endif
>
> Shouldn't we always get this from linux/compiler.h?

I'll think about this some more as this file gets linked into the tools as well as the firmware.

But probably.

>
>> +__weak int board_fit_image_require_verified(void)
>> +{
>> +       return 1;
>> +}
>> +
>>  int fit_image_verify_with_data(const void *fit, int image_noffset,
>>                                const void *data, size_t size)
>>  {
>> @@ -1209,6 +1217,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>>
>>         /* Verify all required signatures */
>>         if (IMAGE_ENABLE_VERIFY &&
>> +           fit_image_require_verified() &&
>>             fit_image_verify_required_sigs(fit, image_noffset, data, size,
>>                                            gd_fdt_blob(), &verify_all)) {
>>                 err_msg = "Unable to verify required signature";
>> @@ -1230,7 +1239,9 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
>>                                                  &err_msg))
>>                                 goto error;
>>                         puts("+ ");
>> -               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
>> +               } else if (IMAGE_ENABLE_VERIFY &&
>> +                               fit_image_require_verified() &&
>> +                               verify_all &&
>
> reading through this it's quite confusing.
>
> We have IMAGE_ENABLE_VERIFY, a compile time constant that will be true
> if CONFIG_FIT_SIGNATURE is enabled.
>
> We're adding a function that will override this.
>
> So we could have a function:
>
> __weak bool fit_enable_verification(void)
> {
>    return IMAGE_ENABLE_VERIFY;
> }
>
> The downside of this would be if a board were to implement this but
> not have FIT_SIGNATURE enabled then they could return true when they
> shouldn't. You could go back to this:
>
> static bool fit_enable_verification(void)
> {
>    return IMAGE_ENABLE_VERIFY && board_fit_image_require_verified();
> }
>
> And drop the ifdefs from image.h

This sounds attractive, let me poke at it.

Thanks for thinking about it.

Andrew
diff mbox series

Patch

diff --git a/Kconfig b/Kconfig
index c3dfa8de47c8..11f796035ae4 100644
--- a/Kconfig
+++ b/Kconfig
@@ -322,6 +322,15 @@  config FIT_SIGNATURE
 	  format support in this case, enable it using
 	  CONFIG_IMAGE_FORMAT_LEGACY.
 
+if FIT_SIGNATURE
+config FIT_RUNTIME_SIGNATURE
+	bool "Control verification of FIT uImages at runtime"
+	help
+	  This option allows board support to disable verification of
+	  signatures at runtime, for example through the state of a GPIO.
+endif # FIT_SIGNATURE
+
+
 config FIT_SIGNATURE_MAX_SIZE
 	hex "Max size of signed FIT structures"
 	depends on FIT_SIGNATURE
diff --git a/common/image-fit.c b/common/image-fit.c
index 3c8667f93de2..eb1e66b02b68 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1199,6 +1199,14 @@  static int fit_image_check_hash(const void *fit, int noffset, const void *data,
 	return 0;
 }
 
+#ifndef __weak
+#define __weak
+#endif
+__weak int board_fit_image_require_verified(void)
+{
+	return 1;
+}
+
 int fit_image_verify_with_data(const void *fit, int image_noffset,
 			       const void *data, size_t size)
 {
@@ -1209,6 +1217,7 @@  int fit_image_verify_with_data(const void *fit, int image_noffset,
 
 	/* Verify all required signatures */
 	if (IMAGE_ENABLE_VERIFY &&
+	    fit_image_require_verified() &&
 	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
 					   gd_fdt_blob(), &verify_all)) {
 		err_msg = "Unable to verify required signature";
@@ -1230,7 +1239,9 @@  int fit_image_verify_with_data(const void *fit, int image_noffset,
 						 &err_msg))
 				goto error;
 			puts("+ ");
-		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
+		} else if (IMAGE_ENABLE_VERIFY &&
+				fit_image_require_verified() &&
+				verify_all &&
 				!strncmp(name, FIT_SIG_NODENAME,
 					strlen(FIT_SIG_NODENAME))) {
 			ret = fit_image_check_sig(fit, noffset, data,
@@ -1849,7 +1860,9 @@  int fit_image_load(bootm_headers_t *images, ulong addr,
 		if (image_type == IH_TYPE_KERNEL)
 			images->fit_uname_cfg = fit_base_uname_config;
 
-		if (IMAGE_ENABLE_VERIFY && images->verify) {
+		if (IMAGE_ENABLE_VERIFY &&
+				fit_image_require_verified() &&
+				images->verify) {
 			puts("   Verifying Hash Integrity ... ");
 			if (fit_config_verify(fit, cfg_noffset)) {
 				puts("Bad Data Hash\n");
diff --git a/include/image.h b/include/image.h
index 937c7eee8ffb..19ea743af08f 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1103,6 +1103,15 @@  int calculate_hash(const void *data, int data_len, const char *algo,
 # define IMAGE_ENABLE_VERIFY	0
 #endif
 
+/*
+ * Further, allow run-time control of verification, e.g. via a jumper
+ */
+#if defined(CONFIG_FIT_RUNTIME_SIGNATURE)
+# define fit_image_require_verified()	board_fit_image_require_verified()
+#else
+# define fit_image_require_verified()	IMAGE_ENABLE_VERIFY
+#endif
+
 #ifdef USE_HOSTCC
 void *image_get_host_blob(void);
 void image_set_host_blob(void *host_blob);