Skip to content

Refuse Secure Boot enrolment on 32-bit UEFI (GH-140) - #142

Merged
mastacontrola merged 1 commit into
masterfrom
refuse-secureboot-enrolment-on-ia32
Aug 4, 2026
Merged

Refuse Secure Boot enrolment on 32-bit UEFI (GH-140)#142
mastacontrola merged 1 commit into
masterfrom
refuse-secureboot-enrolment-on-ia32

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Closes #140.

The enrolment task had no architecture check. On an ia32 client that produced one of two wrong outcomes.

Outside Setup Mode it staged a MOK request, printed a one-time password and "a blue MOK Manager screen appears on the next boot", and reported Task Complete. Nothing will ever read that MokNewMokList is a shim variable and no Microsoft-signed 32-bit shim exists for the machine to boot. Same false-success class as #136.

In Setup Mode it was worse than useless, and this is the part that reversed the recommendation in #134:

shim signed iPXE
x86_64 shimx64.efi x86_64-sb/snponly.efi, ipxe.efi
arm64 shimaa64.efi arm64-sb/snponly.efi, ipxe.efi
ia32 none none

The db write works — nothing in it is architecture-specific — which is exactly why "degrade to the db path" looked reasonable. But it has no chain to make bootable; FOG serves ia32 clients an unsigned i386-efi/snponly.efi. And Setup Mode is the only state where the task can run there, because nothing is enforcing. Path 1 finishes by writing the PK, which is what leaves Setup Mode. So degrading takes a machine FOG can image today, makes it enforceable, and leaves it with nothing signed to load — irreversibly from the client's side.

The change

  • sbPlatformBits() reads /sys/firmware/efi/fw_platform_size — firmware width, not CPU width. ia32 UEFI overwhelmingly runs on 64-bit CPUs, so uname -m answers a different question.
  • fog.enrollsb refuses before the certificate fetch and before the already-trusted short-circuit. No db contents make enrolment useful here.
  • An unreadable value reads unknown and callers proceed — refusing on it would break x86-64 clients to guard a case the kernel has made impossible since 4.14.
  • ADR-0009 corrected: it said "path 1 would still work there", true of the write and wrong about the outcome.

Tests

47 cases (was 43), mutation-checked against pinning the output to 64, passing the raw value through, and dropping the readability guard.

That third mutation initially passed — a missing file reaches unknown through the wildcard either way, so the guard was only observable on stderr. Rather than claim coverage the test didn't have, the redundant 2>/dev/null came off and a case now asserts the silence, which is the behaviour that matters on a BIOS-booted client. Given this ADR has now recorded three designs that passed their tests and were still wrong, that seemed worth doing properly.

The refusal itself is in the entry point beside the existing nonefi/noefivars ones, which the harness also cannot reach — it sources the library, not fog.enrollsb. Verified by lifting the guard verbatim out of the script and running it against 32 / 64 / absent.

🤖 Generated with Claude Code

The enrolment task had no architecture check at all. On an ia32 client
that meant one of two wrong outcomes.

Outside Setup Mode it staged a MOK request, printed a one-time password
and "a blue MOK Manager screen appears on the next boot", and reported
Task Complete. Nothing will ever read that MokNew: MokList is a shim
variable, and no Microsoft-signed 32-bit shim exists for such a machine
to boot. Same false-success class as GH-136.

In Setup Mode it was worse than useless. The db write itself works --
nothing in it is architecture-specific -- which is exactly why
"degrade to the db path" looked like the reasonable answer. But the
write has no chain to make bootable: ipxe/shim publishes shimx64.efi
and shimaa64.efi only, iPXE's ipxeboot.tar.gz ships x86_64-sb/ and
arm64-sb/ only, and FOG serves ia32 clients an unsigned
i386-efi/snponly.efi. Meanwhile Setup Mode is the only state where the
task can run there at all, and path 1 finishes by writing the PK --
which is what leaves Setup Mode. So it took a machine FOG could image,
made it enforceable, and left it with nothing signed to load. PK is not
reversible from the OS; recovery is a firmware trip.

sbPlatformBits() reads /sys/firmware/efi/fw_platform_size. That is
firmware width, not CPU width, and the distinction matters: ia32 UEFI
overwhelmingly runs on 64-bit CPUs, so uname -m would answer a
different question and answer this one wrongly. An unreadable value
reads as "unknown" and callers proceed -- refusing on it would break
x86-64 clients to guard a case the kernel has made impossible since
4.14.

The refusal sits in fog.enrollsb beside the nonefi/noefivars ones,
before the certificate fetch and before the already-trusted
short-circuit: no db contents make enrolment useful here, so no state
exists in which continuing tells the admin anything more useful.

The 0009 ADR said "path 1 would still work there", which was true of
the write and wrong about the outcome. Corrected, along with the note
that FOG signing its own i386-efi/ipxe.efi with the key already going
into db would change the answer -- shim only exists to bridge to
Microsoft's trust, and that bridge is redundant once FOG's key is in db.

Four cases added to tests/checks/secureboot.sh, mutation-checked
against pinning the output to 64, passing the raw value through, and
dropping the readability guard. That last mutation initially passed:
the wildcard yields "unknown" for a missing file either way, so the
guard was only observable on stderr. Rather than claim coverage the
test did not have, the redundant 2>/dev/null came off and a case now
asserts the silence -- which is the behaviour that actually matters on
a BIOS-booted client.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mastacontrola
mastacontrola merged commit 1a58b51 into master Aug 4, 2026
@mastacontrola
mastacontrola deleted the refuse-secureboot-enrolment-on-ia32 branch August 4, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Secure Boot: refuse enrolment on 32-bit UEFI instead of half-enrolling it

1 participant