IRC channel logs

2023-11-10.log

back to list of logs

<janneke>in a few moments: https://hpc.guix.info/events/2023/workshop/program/#how-to-get-started-using-guix
<janneke>=> https://www.youtube.com/watch?v=dT5S72x18R8
<janneke>hmm, maybe i misread the schedule?
<oriansj>yeah and default will have to be the last statement of the switch
<oriansj>we really need to clean up armv7l and AArch64 M1 assembly
<oriansj>but switch statements should be in M2-Planet shortly (doing tests now)
<Googulator>Hi All! For a few days now, I have been experimenting with live-bootstrap as a provable anti-Trusting-Trust mechanism, i.e. a means to establish a trusted compilation environment that can compile modern software, while also being free of any self-propagating backdoors (at least beyond what could fit in a 512-byte boot sector image, which is not
<Googulator>much).
<Googulator>Primary the bare metal route, on some older hardware that's presumed trustworthy.
<oriansj>^_^ good fun
<Googulator>Unfortunately, I see a potential attack vector in the current implementation: assuming that I can't trust my current, modern system used for preparing the bare metal images (which would pretty much be the starting assumption for such an endeavor), there's always a possibility that when I write the image to disk for bare metal bootstrap, what gets
<Googulator>written isn't what I _think_ is being written; specifically that either there's more binary code written than just that one sector, or that the source written to disk (the srcfs) doesn't match what I can view on my host machine. I've been working on solving this for the last few days, and came up with some pretty wild attack vectors, as well as
<Googulator>potential ways to block them.
<Googulator>For the issue of "more binary code written than acknowledged", I'm thinking of a hardware-based countermeasure: some kind of flash drive/SSD build in an open-source way using parallel NAND flash (with actual A0...An address lines) and a discrete controller.
<vagrantc>sure, you can always work on custom hardware or take everything down another layer deeper!
<Googulator>With such a drive, it should be possible to add a physical switch to the A8 line (assuming the output is byte-oriented - the exact address line depends on the width of the parallel flash's data bus), such that byte address 0x200 will wrap back to 0x0 when the switch is open.
<Googulator>i.e. when the boot sector tries to load sector 1; it instead reloads itself.
<Googulator>We can then format the stage2 hex0 code in such a way to have it start with a comment, and modify the code of the boot sector to check if it's reading itself, a sector that begins with a hex0 comment, or something else.
<Googulator>If it sees itself, it tries again until it sees something. If it sees a hex0 comment, it proceeds with normal boot. Anything else, and it stops with an error, as that indicates a compromise.
<Googulator>Additionally, provide some visual or serial-console-output evidence as to whether it's still rereading itself, or has moved on to actually parsing hex0.
<oriansj>well microcode and firmware attacks are a problem until we make our own hardware
<Googulator>(e.g. printing a dot on the screen or serial out everytime it rereads itself)
<oriansj>and that isn't even including the more exotic Nexus intruder types of attacks
<oriansj>where you need to bootstrap your lithography machines to be sure the circuits you print/make actually match your design
<Googulator>I'm assuming that the hardware used for the bare metal bootstrap is old enough that even if it's compromised, it won't recognize the bootstrap code and be able to interfere - for example, something from 2004.
<oriansj>fair enough assumption to have when making progress (no need to solve all issues right off the bat)
<Googulator>The challenge is instead in seeding that old system with something that won't successfully bootstrap itself if it's compromised in any way (assuming no compromise can be hidden in a 512-byte boot sector while retaining its apparent normal functionality).
<Googulator>So now, we boot the 2004 system with our specially prepared flash disk, with the switch open. If there's no compromise, it starts printing a series of dots.
<vagrantc>would be curious to apply bootstrappable builds + reproducible builds + diverse double-compiling ... each adds some degree of strong confidence, but all together is quite solid
<vagrantc>i think live-bootstrap does actually result in bit-for-bit identical results ... so the main thing would be to introduce an alternate bootstrap path that ends in the same bit-for-bit identical result
<Googulator>The next change we need to make to the boot sector (builder-hex0-x86-stage1) is to make it print every byte of hex0 code it sees.
<Googulator>And now, we flip the switch - and if nothing has been compromised, at that exact moment, the boot sector stops printing dots, and instead prints out hex0 source for the next stage.
<Googulator>If anything else happens - compromise!
<Googulator>Assuming we have a trustworthy way of recording and later reviewing the data printed out, we can then verify that it is indeed the code we thought we've written out in the first place.
<Googulator>(An actual printer printing to paper would be ideal for security and trust, but it would probably be too slow.)
<stikonas>well, there is no way to enter bytes into memory on modern machines
<oriansj>well the problem is up until mescc-tools-extras we have no ability to do sha256sum on the input files
<stikonas>you would have to go older to something like PDP-8 with front panel switches
<stikonas>or maybe one of those arm/riscv SoCs with SPI bus
<Googulator>With what I'm proposing, there's no need to directly enter bytes.
<stikonas>it might be possible to program SPI manually
<oriansj>I'm opted for a hardware tape readers
<Googulator>But if you want to go that route, I2C has certainly been bitbanged using discrete mechanical switches.
<oriansj>and we have how to hand toggle PROMs
<Googulator>For my proposal to work, only a single mechanical switch is required - the one in line with the parallel flash's A9 line.
<oriansj>sounds interesting
<Googulator>or A8 rather
<Googulator>You close it when programming the flash using the untrusted host system, then open it, plug into the bootstrap machine, boot to the boot sector, wait for dots to start printing, then you close the switch, and off we go.
<Googulator>What makes this work is the fact that assuming no compromise, the first thing the boot sector (residing in LBA #0) needs to read is LBA #1, but with the switch open, we mask the low-order bit of the LBA address, so LBA #1 becomes a copy of #0, #3 of #2, and so on.
<oriansj>so a source code Flash chip and a bootstrap binary ROM chip (or unwritable flash)
<Googulator>A binary ROM would probably add even more trust, but really a single Flash chip is enough.
<oriansj>functioning as say an IDE/SATA drive would enable any older system to be leveraged
<Googulator>LBA #0 holds the builder-hex0 stage1 boot sector (modified to fit my proposal), the rest holds the stage2 hex0 source and the srcfs.
<oriansj>yeah, that would work
<Googulator>I was thinking more in terms of USB - this is where using a machine from around 2004 comes in, as USB flash drives were already common at that point, and many motherboards from that era can boot off USB just fine.
<Googulator>And with 2004-era USB drives, there's a good chance they would have the discrete controller-and-NAND construction needed.
<Googulator>(i.e. with an actual PCB trace connecting the A8 line between the controller and the NAND that can be cut and wired to a switch)
<oriansj>would be neat to see done
<Googulator>So the procedure is: create image on untrusted host, close switch, plug flash drive into untrusted host, write the image to it.
<Googulator>Unplug, open the switch, plug into target machine, boot off it, and watch for dots.
<Googulator>Now, you can start recording the log output using whatever trusted mechanism you have (old VHS camera, mechanical printer, some purpose-built device for this purpose... or just slow things down enough so you can read it live), and close the switch.
<oriansj>I would suggest having the ability to connect to an external circuit, enabling you to manually the validate the first 512bytes
<oriansj>that way you can also catch if the untrusted host puts untrusted values in the first 512bytes
<Googulator>Boot sector prints out the stage2 hex0 source code while compiling it, then hands off to stage2, which likewise prints out the srcfs as it loads.
<oriansj>fair enough
<oriansj>but the boot sector needs a way to be inspected
<Googulator>An external circuit (if itself trusted) would help validate the exact contents of the boot sector - however, it's not really required for trust, because I highly doubt anyone can write a functional boot sector, plus a backdoor, plus some code that can predict when I'm gonna flip the switch, in just 512 bytes.
<oriansj>completely fair
<Googulator>You can of course do this several times, and gain more confidence that the dots stopping at just the right moment weren't just the backdoor code getting lucky.
<Googulator>Anyway, once the whole srcfs is loaded, the next stage of the bootstrap process starts with "hex0 ./bootstrap-seeds/POSIX/x86/hex0_x86.hex0 ./bootstrap-seeds/POSIX/x86/hex0-seed; hex0 ./bootstrap-seeds/POSIX/x86/kaem-minimal.hex0 ./bootstrap-seeds/POSIX/x86/kaem-optional-seed; ./bootstrap-seeds/POSIX/x86/kaem-optional-seed ./kaem.x86" inside
<Googulator>builder-stage2's shell, kicking off the build of everything within the srcfs and beyond.
<Googulator>Then, once we reach the point where the srcfs is no longer needed, we securely erase it from the target, so the only place it remains is on our trusted recording device (or paper), and on the untrusted host. This will come in important later.
<Googulator>From this point on, we're getting the remaining sources over the internet, and running the rest of the bootstrap all the way up into GCC 13.x.
<Googulator>Also when the srcfs gets erased, we pause to unplug the modified flash drive.
<Googulator>Once we have modern GCC and our shell, we plug in another such specially prepared (but still empty) flash drive, with the switch closed - and use the bootstrapped system to run live-bootstrap again, writing to that drive. Then, we use that drive to bootstrap again the same way we did the first time, all the way until the entire srcfs is printed. Of
<Googulator>course, record everything with the trusted recorder.
<Googulator>Now, we can compare the records from the 2 stage2 and srcfs printouts. If they match - we can be sure no backdoor propagated from our untrusted system to the bootstrapped one!
<Googulator>(In fact, since srcfs resides in RAM once it's loaded, it's better to unplug the first flash drive just as srcfs loading finishes.)
<Googulator>This is the reason we erased srcfs when it was no longer needed - to leave no way for the rest of the system (build from code downloaded later) to just copy the original srcfs instead of reconstructing it from source.
<Googulator>The only issue that remains at this point is the fact that all of the code we compiled and executed theoretically had write access to all of the sources that built it, so a sophisticated attacker could send us sources that when compiled, alter the previously downloaded source code to hide a backdoor. In such a case, when we then try to audit the
<Googulator>sources left behind on the system, we're 1. potentially reading sources that have been altered, and 2. potentially reading those sources through backdoored tools that might not present the sources faithfully to us.
<oriansj>hmmm
<Googulator>To close this hole, 3 things are needed: first, make sure that the post-srcfs of the build keeps the downloaded sources for later auditing in the first place; second, include hashes of every source file or package that will be downloaded later in the srcfs, so we can compare against the trusted recording (AFAIK live-bootstrap already does this),
<Googulator>and finally, make a somewhat extended version of the srcfs-built system (still buildable entirely via the srcfs mechanism) that's powerful enough that we can plug in the drive containing our bootstrapped system, and without executing anything from it, be able to review and audit all the source code present.
<Googulator>(as well as recompute hashes of the source packages kept)
<Googulator>If all the hashes recomputed in this "audit-srcfs" system match the ones in the trusted record, then when we view the retained sources retained in the bootstrapped image from the "audit-srcfs" system, we're reading the true sources that built the bootstrapped image.
<Googulator>(oops, too many retaineds)
<oriansj>Googulator: do we need cryptographically secure hashes for the steps leading up to mescc-tools-extras?
<oriansj>or would a CRC type of hash be sufficient?
<oriansj>as one could implement that in only a few dozen bytes
<oriansj>and something like that could fit in the builder-hex0-mini along with existing functionality
<oriansj>then instead of dots, you could see checksums
<oriansj>of not only the sources but also the resulting binaries
<Googulator>Dots are only printed while waiting for the switch to toggle
<Googulator>From that point on, the plan is to print the sources themselves
<Googulator>So that each byte of source code is printed and recorded before any binary built from it had a chance to execute
<Googulator>Hence a hash at this stage wouldn't be enough
<oriansj>to say a line printer over a parallel port I am assuming?
<Googulator>I was thinking either a UART or to a VGA-style console
<Googulator>But a parallel port could work as well
<Googulator>The key to countering malicious source code that modifies itself after it's compiled and executed is to make sure that every source byte up to that point is printed before it's executed
<oriansj>well a VGA-style console tends to have the limit of time and only so many lines (for people who don't read fast it is easy to miss different text)
<Googulator>VGA has the advantage that it's analog RGB video, which can be recorded using consumer electronics, hopefully with enough precision so that it can be read back later
<Googulator>VHS probably wouldn't cut it, but a TiVo-style PVR could
<oriansj>well a UART or a parallel port could directly write the output into a storage media of choice (be it paper or digital)
<Googulator>But you need a trusted way to then view that record
<Googulator>Paper doesn't have this issue, but it's slower to write than to read
<Googulator>vs VGA which can scroll faster than you can read it, so long as it's not too fast for a PVR to record
<Googulator>& then you can play it back slowed down to read
<oriansj>depends if you have an old commadore line printer
<Googulator>How fast are those?
<oriansj>those could hit 30 pages a minute
<oriansj>but you were limited to petscii characters and a ribbon cable
<Googulator>30 pages/minute? That sounds very fast, even by modern printer standards.
<oriansj>plus had a bad habit of jamming and unexpectedly dying; which is why their write speed was usually software limited
<Googulator>That's a whole page every 2 seconds.
<oriansj>10 pages per minute was pretty common in that era with some hitting 2500 lines per minute
<vagrantc>yeah, printer speeds slowed down significantly with the transition to ink and toner
<oriansj>and the resultion went way up
<vagrantc>yeah, very pretty.
<oriansj>we can do images now
<oriansj>which would be nice if I actually printed anything anymore
<oriansj>stikonas: the switch prototype with test is up
<stikonas>oh, so quickly!
<oriansj>janneke: feel free to let me know what I did wrong so that you can use it in mes.c ^_^
<oriansj>it is only 214 lines of code
<oriansj>and the test cases definitely could use some expanding
<stikonas>oriansj: can we not optimize risc-v assembly at else if((RISCV32 == Architecture) || (RISCV64 == Architecture)) emit_out("rd_a0 rs1_a0 rs2_a1 sub\nrs1_a0 @8 bnez\n$_SWITCH_CASE_"); ?
<stikonas>(line 2201)
<stikonas>here we are just comparing two registers?
<stikonas>hmm, let me think...
<stikonas>hmm, maybe not...
<stikonas>oriansj: ok, I think it makes sense
<stikonas>it would be interesting now to test it with mes, but of course one would first have to restore switches in mes.c...