All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
To: Simon Glass <sjg@chromium.org>
Cc: u-boot <u-boot@lists.denx.de>
Subject: Re: two questions on verified boot
Date: Thu, 27 Jan 2022 16:41:51 +0100	[thread overview]
Message-ID: <7d711133-d513-5bcb-52f2-a9dbaa9eeded@prevas.dk> (raw)
In-Reply-To: <CAPnjgZ3z6uRO1vF-Y02awF3shjGsgJOWgfuDghajZk0=yfKONA@mail.gmail.com>

On 27/01/2022 16.06, Simon Glass wrote:
> Hi Rasmus,
> 
> On Sun, 21 Nov 2021 at 07:55, Rasmus Villemoes
> <rasmus.villemoes@prevas.dk> wrote:
>>
>> (1) When one wants to get rid of CONFIG_LEGACY_IMAGE_FORMAT, one also
>> has to wrap any boot script in a FIT rather than a uImage. While it's
>> not directly documented anywhere how to do that, it seems that a minimal
>> .its for achieving it is
>>
>> /dts-v1/;
>>
>> / {
>>         description = "U-Boot script(s)";
>>
>>         images {
>>                 default = "boot";
>>                 boot {
>>                         description = "Bootscript";
>>                         data = /incbin/("boot.txt");
>>                         type = "script";
>>                         compression = "none";
>>                         hash-1 {
>>                                 algo = "sha256";
>>                         };
>>                 };
>>         };
>> };
>>
>> [The UX when one doesn't guess that the description string is mandatory
>> is rather sad, but that's a separate story.]
>>
>> Now, I can get that signed if I include a signature-foo node inside the
>> "boot" node, and also add a dummy empty /configurations node (otherwise
>> mkimage refuses to process it). But that will only work if I have added
>> a "required = image" property with the public key; if I want to use the
>> safer/saner "required = conf", how do I make sure any boot script is
>> properly signed?
>>
>> The code in source.c only cares about the images node and calls
>> fit_image_verify(), and there's no concept of "configuration" and
>> combining multiple images when talking about a simple boot script.
> 
> By then the configuration should have been checked, though, right?

By what?

 At
> least, that is how bootm works.
> 
> So it seems that the scripts are being done in a different way.

The thing is, for a script there's really no such thing as a
"configuration", there are not multiple subimages that need to be
stitched together.

>>
>> (2) Assuming for the moment that I would be happy with just using
>> required=image, am I right in that not only does that mean that the
>> combination of kernel/fdt/initramfs is not verified, merely the
>> individual parts, but more importantly (a mix'n'match attack isn't
>> really very likely), _only_ the data property in each node is part of
>> what gets signed, not the other important properties such as load= and
>> entry=? IOW, suppose I have a FIT image with
> 
> Yes the 'image' check does not protect against a mix & match attack -
> see doc/uImage.FIT/signature.txt

I don't care about mix'n'match, they are completely unlikely to be
relevant. But...

>>
>>   images {
>>      kernel {
>>         data = blabla;
>>         load = 0x1000000;
>>         entry = 0x10000000;
>>         signature {
>>            ... // correct signature of blabla
>>         };
>>      };
>>    };
>>
>> and I know that the boot process uses $loadaddr = 0x40000000. What is to
>> stop me from modifying that FIT image to read
>>
>>   images {
>>      kernel {
>>         data = blabla;
>>         load = 0x1000000;
>>         entry = 0x400abcde;
>>         signature {
>>            ... // correct signature of blabla
>>         };
>>      };
>>   };
>>   some-other-node {
>>       pwned = /incbin/("pwned");
>>   };
>>
>> where 0xabcde is chosen to coincide with where the data part of the
>> pwned property lies in the modified FIT? (That pwned property can be put
>> anywhere; I could even just replace the signer-name property inside the
>> signature node with a value of "mkimage\0<padding><my payload>".)
> 
> Yes I believe that is right.

... this then means that 'required = "image"' is not just a little less
safe than the "signed configurations" model, it is completely and
utterly broken.

>>
>> In fit_config_process_sig(), there's this elaborate dance with
>> fit_config_get_data()/fdt_find_regions() which, AFAICT, ends up
>> including all the property values (and the FDT_PROP tags and string
>> offsets etc.), and then we call info.crypto->sign() with some
>> appropriate region_count.
> 
> Yes
> 
>> But in fit_image_process_sig(), we call
>> info.crypto->sign() with nregions==1, and AFAICT, the data being signed
>> is just the value of the "data" property, nothing else.
> 
> Yes, this matches the behaviour of the existing hashing properties.
> They only hash on the data itself.
> 
> We could expand this to include the properties of the image node, I
> suppose. But do note that you really need 'config' signing to make
> things secure.

That's kind of what I guessed, but to rephrase my question: How do I
sign a boot script and have that verified, when the source.c code only
calls fit_image_verify(), which eventually calls
fit_image_verify_required_sigs() which only cares about the keys that
have 'required = "image"'.

I'd prefer to just have one public key for verifying both the boot
script and the kernel FIT image. I don't think it would work very well
to have two keys (possibly the same one just added under different key
names), one with required=image and one with required=conf, because
AFAICT then the kernel FIT image would have to have signatures on _both_
image and configuation nodes. If I add just one key with required=conf,
the boot script isn't verified at all, and if it says required=image,
well, then I'm vulnerable to the trivial modification of entry=
mentioned above.

Rasmus

  reply	other threads:[~2022-01-27 15:42 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-21 14:55 two questions on verified boot Rasmus Villemoes
2021-11-21 19:32 ` Dhananjay Phadke
2022-01-27 15:06 ` Simon Glass
2022-01-27 15:41   ` Rasmus Villemoes [this message]
2022-03-12  2:24     ` Simon Glass

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=7d711133-d513-5bcb-52f2-a9dbaa9eeded@prevas.dk \
    --to=rasmus.villemoes@prevas.dk \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.