azonenberg,
@azonenberg@ioc.exchange avatar

How crazy/horrible/stupid would it be to write a single-pass streaming parser for ELF as part of a firmware updater?

More specifically, you're given a chance to look at each byte of data once. You can either write it to flash immediately, update some local variables (like "offset of .text"), or ignore it.

But once you've seen a given part of the file, you can't rewind and look at it again later (since I'm flashing an image that might be larger than available RAM).

How likely is this to fail in practice? I'm not asking if one of the POC||GTFO editors could craft an ELF that would break this, I'm sure they could. But if I control the linker script generating the file, and have the parser simply refuse to process any file that doesn't play by my rules, am I probably OK?

0h00000000,
@0h00000000@ioc.exchange avatar

@azonenberg For my updates, I have the crypto accelerators on STM32L4+, and I have server generate a SHA hash and send it with file, and I have STM32L4+ generate a SHA hash as it downloads it and verity before rebooting target. I don't think CRC is very reliable for larger data.

azonenberg,
@azonenberg@ioc.exchange avatar

@0h00000000 Initially I won't have any file-level integrity checks since there's multiple layers of checksumming already (my updates are going to run over SFTP so there's going to be Ethernet CRC, TCP checksum, and then AES-GCM in the SSH layer).

If I'm updating a different MCU (i.e. not the one the SSH is terminating on) I'll probably add a CRC/SHA for each flash block, computed on the top level MCU and verified on the one being flashed. Some details still TBD.

tj,
@tj@altelectron.org.uk avatar

@azonenberg Does SFTP guarantee that file transfers are correct? TCP only promises that segments are delivered to the receiving application has to ensure they are delivered and processed correctly. Sadly all the layers below will just save corruption in those layers and could easily miss a crash between a valid segment and the data making it to where it needs to go

azonenberg,
@azonenberg@ioc.exchange avatar

@tj SFTP runs over SSH so there's cryptographic integrity checks (in this case AES-GCM as that's the only cipher suite my stack supports) over the entire data stream.

The only place I could have corruption is in RAM (SEU) or on the bus between the MCU running the SSH protocol and the device being flashed (this is a complex system with four micros and an FPGA, and the SSH protocol only runs on one of the MCUs)

feld,
@feld@bikeshed.party avatar

@tj @azonenberg TCP checksums are not good enough

> "No muck? rad!" and "No luck? sad!" have identical checksums if the rest of the packet is identical.

azonenberg,
@azonenberg@ioc.exchange avatar

@feld @tj Yeah, but that's one of the advantages of running over SFTP.

Now I have "free" AES-GCM integrity checks over my SFTP protocol data stream.

feld,
@feld@bikeshed.party avatar

@azonenberg @tj sure that prevents issues from any intermediaries passing the traffic from flipping bits

but it doesn't fix it if the origin flips the bits in its own memory before AES-GCM

azonenberg,
@azonenberg@ioc.exchange avatar

@feld @tj Correct.

Which is why the long term vision is to have signed update files where there's an extra ELF section containing a curve25519 signature over the loadable parts of the firmware (so .text, .data, etc). Haven't worked out exact details of what parts of the ELF need signing but roughly speaking it's going to be metadata + contents of all PT_LOAD segments.

By default it'll check against my root signing key but given admin-level SSH access to the device an end user will be able to revoke my key and/or add their own.

It won't be full secure boot (JTAG/SWD firmware updates won't be integrity checked, and once the image is burned to flash I might do a boot time CRC but nothing more than that) but should be more than sufficient to catch corrupted downloads.

Milestone 1 will be just basic "flash this file, i pinky promise it's OK" with SSH crypto to guard against bitflips in transit.

feld,
@feld@bikeshed.party avatar

@azonenberg @tj I defer to your expertise as you clearly know a lot more about firmware stuff than I do 😅

equinox,
@equinox@chaos.social avatar

@azonenberg if you have cooperation from the linker to not write headers in a completely stupid way, it should be doable. Mostly a question of having the PHDRs at the top of the file (which is default but /theoretically/ they could be at the end, in which case you'd be fucked)

equinox,
@equinox@chaos.social avatar

@azonenberg also since you mentioned .text (I assume it was only as an example, but anyway) — you should not be looking at section headers, program headers are all you need and want. You can in fact remove the section headers with sstrip and make the binary a bit smaller (might matter if things are slow).

azonenberg,
@azonenberg@ioc.exchange avatar

@equinox Yeah I've written elf loaders before I'd be processing all non empty PT_LOAD phdrs.

azonenberg,
@azonenberg@ioc.exchange avatar

@equinox File overhead shouldn't be bad as long as it's not e.g. a fully unstripped binary with symbols.

I'll be pulling the ELF over 10GbE into a fifo on the FPGA, reading it out over quad SPI (~200 Mbps) to the main micro, parsing the ELF there, then pushing only the actual flash content over spi to the front panel (slow bus but bottlenecked on writes)

equinox,
@equinox@chaos.social avatar

@azonenberg for completeness, if the image is relocatable (it probably wouldn't be, unless you're trying to do some fancy dual image shenanigans), you'd also need to buffer all the relocations in RAM (and rely on the fact they're emitted in front of the actual loaded parts they apply to, which, again, is default but not required)

[and again I assume you probably know this already 😅]

azonenberg,
@azonenberg@ioc.exchange avatar

@equinox Not doing relocations. If I do A/B images each image will be explicitly built for one slot or the other.

(Another situation where elf metadata would come in handy vs a flat binary)

forthy42,
@forthy42@mastodon.net2o.de avatar

@azonenberg Why not objcopy it to binary in the build process?

azonenberg,
@azonenberg@ioc.exchange avatar

@forthy42 That's an option, but then I lose a lot of useful metadata at flash time.

In particular, once I start doing secure update, I want to add a signature as an additional ELF section.

The plan would be that I'd read the firmware, stream it out to flash but set a flag for the bootloader to say "unverified image, don't boot it", then check the signature and if it's good, tell the bootloader "ok you're free to boot".

Or alternatively have the bootloader check the sig every boot, but that's more work and would slow things down. Either way, the additional metadata is helpful so I'd like to keep things as ELF as far as I can.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • DreamBathrooms
  • magazineikmin
  • InstantRegret
  • thenastyranch
  • Durango
  • Youngstown
  • ngwrru68w68
  • slotface
  • everett
  • rosin
  • osvaldo12
  • kavyap
  • cubers
  • mdbf
  • JUstTest
  • khanakhh
  • cisconetworking
  • GTA5RPClips
  • modclub
  • tacticalgear
  • ethstaker
  • tester
  • normalnudes
  • anitta
  • Leos
  • provamag3
  • megavids
  • lostlight
  • All magazines