>Nondeterministic codegen is just scary.
Why not focus on deterministic codegen only? Caring about some metadata changing does not seem to be as useful from a security perspective.
If the metadata were neatly separated from the executable portions of an artifact then it indeed wouldn't be too much of an issue[1], but it often isn't. It sometimes gets embedded into strings and other places in the executable itself where it theoretically could have an impact on the runtime (and of course makes executable signatures unreliable, etc.). Without that separation comparing two potentially-the-same executables becomes equivalent to the Halting Problem.
[1] You could sign only portions of the executable, for example... but such signature schemes are brittle and error-prone in practice, so best avoided. So you'd ideally want any and all metadata totally separate from the executable.
If there is a backdoor in the code there is a backdoor regardless of if there is an extra timestamp that exists.
This way anyone who signs modified code can be caught. This is especially easy with open source projects. Incidentally, Debian is working very hard on deterministic builds.
Code signatures have already existed for decades and do not require reproducable builds.
Without deterministic builds, it's possible for the attacker to switch the compiled binary release and sign it with a stolen key with nobody noticing.
I'd argue that if the key being stolen/misused becomes more easily detectable, signing with said key becomes more meaningful.
Certificate Transparency logs only show when new certificates are issued. If a certificate is stolen it is of no use.
It lets issuers show they are trustworthy.
If the NSA could steal a debian key (or coerce a packager), without deterministic builds, they could put a backdoor in a popular Debian package with barely any chance of getting caught.
Deterministic builds make it much easier to detect this. That makes the value of such a stolen/coerced key much lower. Making it much less likely this gets attempted, and likely stopping anyone who used to try this attack.
If you have to make exceptions for some metadata, all of a sudden there's judgement and smarts involved. And judgement can go wrong.
>And judgement can go wrong.
Which is why it is important to have a good design and threat model.
That page has progress reports that are 8.5 years old and the project is not close to be done. There are still thousands of Debian packages to go.
However, at least the problems with this approach are all in one direction: Bits differing might be due to an actual attack or because of weird compiler issues, but if you get the bits to be identical, you know that no funny business is going on.
The proposal to have more complicated rules doesn't have this upside. And you still need to make sure that the things that actually matter are the same (like instructions in your binaries), even if you successfully separated out irrelevant metadata changes.
but why would you assume that the decompiler is not backdoored? It would know to remove the backdoor code, so the fixpoint is not going to show anything.
In practice, you can push the likelihood of this down to arbitrarily small levels. Pick a decompiler that's as unrelated to your compiler as you can find. Then pick a second decompiler that's maximally unrelated to both the compiler and the first decompiler. It's highly unlikely all three tools will be backdoored in a fully compatible way.
This is the whole point of Thompson’s lecture, though.
Not exactly easy, but probably easier than a decompiler that produces human-equivalent source code.
It could be an interesting exercise to bootstrap up from something like this to a working linux environment based solely on source code compilation : no binary inputs. Of course a full linux environment has way too much source code for one person or team to audit, but at least it rules out RoTT style binary compiler contamination.
Timestamps are one of the biggest offenders, but this is also why reproducible builds are important. Nondeterministic codegen is just scary.
Second, and more importantly, many people carry a copy of a trusted compiler around, though it’s rarely mention in attacks like these: their head.
This is also why I'm against inefficient bloated software in general: the bigger a binary is, the easier it is to hide something in it.
Along the same lines, a third idea I have for defending against such attacks is better decompilers --- ideally, repeatedly decompiling and recompiling should converge to a fixed point, whereas a backdoor in a compiler should cause it to decompile into source that's noticeably divergent.