betrusted-io / xous-core

The Xous microkernel
Apache License 2.0
529 stars 85 forks source link

Precursorupdater checks signature version and kernel length, but not signature? #560

Open asharp opened 2 months ago

asharp commented 2 months ago

Hi,

Sorry if i'm missing something here and thanks for the pretty damn awesome project. It looks like the updater is pulling from the jenkins build bot (via https), checking the signature version and kernel size (but not the signature itself) and then flashing the precursor with whatever it was given.

There is encrypt_to_efuse, but that looks like it's encrypting the bitstream it was given, not checking it.

There is secboot.rs in loader, which seems to do a signature check, but if the loader itself is being reflashed from an untrusted source that doesn't seem helpful.

There is the source repo to build from source, but aside from the github gpg key (B5690EEEBB952194) i don't see signed tags from committers, so I'm not sure how i'd verify the repository. And then the updater doesn't seem to have an option to flash from the local repository. That seems to be in betrusted-scripts, but that's via JTAG not usb.

This doesn't make much sense. Is this expected? Is this a bug? Is this part still a work in progress?

Thanks

bunnie commented 2 months ago

Hii @asharp, you are exactly right that the artifact as downloaded from the bot builder is not signed and there isn't a PK certificate to check it against.

This is because we don't trust ourselves with the responsibility of running a build infrastructure that we can certify as "not tampered with" (yet). At the moment the build infrastructure we are using for releases is just a vanilla Ubuntu server with no special procedures to lock it down, little auditing, with access available to multiple users.

We didn't want to create the impression that somehow an artifact from our build server is any more trustable than something you could build locally on your own machine.

One big stumbling block when we were starting the project is we didn't have a cryptographic enclave suitable for storing signatures for builds. That problem, at least, is solved now (we would use a Precursor for that!).

However, we'd also need to distribute a public key certificate, and I never liked the whole PKCS thing. That being said, my thought is maybe we'll add our signing key to a certificate transparency log of some type. It's not perfect but I like what it's done for HTTPS. It disitnermediates paid third parties and governments from being in the position of certificate authorities.

Of course, I'm not a devops person so I don't really know how to implement any of that. And because I'm not a devops person I don't really trust myself to set up a server that could stand up to any determined adversary. I've had enough servers exploited to be humbled about my ability to configure a server correctly. So there's a lot of things that have to happen before I think we could advertise a trustable build binary.

Until then, the recommendation is to build from source locally on your own machine, if you can't trust us. Because really, you shouldn't trust us, at least until we have put together a build infrastucture plan, published it, and made it publicly reviewable so you'd have a reason to trust the measures we have taken.

bunnie commented 2 months ago

As a side note, there is a key slot for a public key for signed builds, it's empty right now in the key enclave inside Precursor. When the day comes, we'll add an option to populate that with a key you choose to trust.

A "good user experience" would argue that we just stick our key in there and give it to people as a default. But I think an honest user experience would be to leave it empty and force a user to make a decision on what provider to trust for their builds.

Probably the middle ground is, populate the field with a default, and then prompt users with a box that 99.9% of people will just click "dismiss" on that offers them to pick their own trusted provider for updates.

Anyways -- all still a work in progress.

asharp commented 2 months ago

Thanks for that, that makes a bit more sense.

Until then, the recommendation is to build from source locally on your own machine, if you can't trust us. Because really, you shouldn't trust us, at least until we have put together a build infrastucture plan, published it, and made it publicly reviewable so you'd have a reason to trust the measures we have taken.

The issue then is without signed commits, or a signed release tarball, how do i trust that the code i checked out is the same code that was committed? If you remember the git horror story, git itself runs on the honor system without signed commits.

Also, an unsigned download involves trusting your build server but also https, etc.

We didn't want to create the impression that somehow an artifact from our build server is any more trustable than something you could build locally on your own machine.

That makes sense, but also isn't really signposted. As a new user running the getting started guide, step 1 is running the updater which doesn't explain the security model implied in the steps you're guided to. Especially as that's the only 'casual' path that doesn't require JTAG and some extra hardware. Although it looks like that shouldn't need JTAG if the updater could be pointed at local images.

bunnie commented 2 months ago

Yes, we should probably start doing signed commits. It's on my list of things to do to figure it out.

That makes sense, but also isn't really signposted. As a new user running the getting started guide, step 1 is running the updater which doesn't explain the security model implied in the steps you're guided to. Especially as that's the only 'casual' path that doesn't require JTAG and some extra hardware. Although it looks like that shouldn't need JTAG if the updater could be pointed at local images.

This is true. There's a balance we have to strike between sign posting all of the problems (of which there are many) and some sort of reasonable experience. The first version of the UI had many more sign posts, most of which most people found confusing and skipped through anyways.

However, for at least the "Precursor" revision, the truth is that it's more of a developer platform to get to something that's got all the right things in the right place. That's why it's called Precursor.

We are starting to reach the point of maturity where we should start paying attention to more of these things though, I think your points are fair and cleaning up the process will be in order. The thing is, we were much, much less mature a year ago, and a lot of these suggestions weren't even actionable back then.

There is a version of the updater that can be pointed at local images, it's here: https://github.com/betrusted-io/betrusted-wiki/wiki/Updates-for-Advanced-Users#usb-updates

The "simple path" is always a struggle to balance between features, sign posting, and meeting the needs of 90% of the users, without overwhelming them with the 10x more options needed for the other 10% of users.

Every time we start adding developer options, it would descend into a hairball, so, advanced users generally get exposed to more rough edges. In part because every advanced user seems to have a different build system, or approach to what they want to do with the device, so it's been impossible to write a document that services the advanced users that isn't twenty pages long and the piece of info you wanted was an obscure line on page 7 which is three revs out of date, which just leads to advanced users complaining there is no documentation because nobody has time to read through the options for everyone else's build.