Skip to content

udisks2: fix LUKS2 auto-unlock failure with TPM2 pin#550

Merged
sergio-correia merged 3 commits intolatchset:masterfrom
sergio-correia:udisks2
Apr 20, 2026
Merged

udisks2: fix LUKS2 auto-unlock failure with TPM2 pin#550
sergio-correia merged 3 commits intolatchset:masterfrom
sergio-correia:udisks2

Conversation

@sergio-correia
Copy link
Copy Markdown
Collaborator

@sergio-correia sergio-correia commented Apr 20, 2026

token_to_jwe() had an off-by-one error: pkt->used-- was meant to exclude the null terminator from the byte count, but snprintf() already excludes it. This truncated the last byte of the JWE authentication tag before piping it to clevis decrypt.

The Rust clevis-pin-tpm2 strictly validates base64url encoding and rejected the truncated tag ("Encoded text cannot have a 6-bit remainder"), causing TPM2 auto-unlock via udisks2 to always fail on LUKS2 devices. Tang was unaffected because the C jose library tolerates truncated base64url input.

snprintf() returns the number of characters written excluding the
null terminator. The pkt->used-- was intended to "remove the null
terminator" from the count, but since snprintf already excludes it,
this incorrectly truncated the last byte of actual JWE data.

This caused LUKS2 auto-unlock via udisks2 to always fail with the
TPM2 pin: the Rust clevis-pin-tpm2 strictly validates base64url
encoding and rejects the truncated authentication tag. The Tang pin
appeared unaffected because the jose C library is lenient about
truncated base64url input.

Also fix the boundary check to use >= instead of >, which would
have accepted a JWE that was silently truncated by snprintf when
the output exactly filled the buffer.

Assisted-by: Claude Opus 4.6
Signed-off-by: Sergio Correia <scorreia@redhat.com>
Extract token_to_jwe() and pkt_t into a separate compilation unit
(token-to-jwe.c/h) so they can be tested independently without
pulling in udisks2, luksmeta, or audit dependencies.

The test verifies the critical invariant that pkt->used equals
strlen(pkt->data) after conversion — the exact condition violated
by the off-by-one bug fixed in the previous commit.

Assisted-by: Claude Opus 4.6
Signed-off-by: Sergio Correia <scorreia@redhat.com>
The check used `r == sizeof(msg)` which only catches exact-fit
truncation. When snprintf would have written more than sizeof(msg)
characters, it returns a value greater than sizeof(msg), and the
old check would miss it. Use `>= sizeof(msg)` to catch all
truncation cases, matching the fix applied to token_to_jwe().

Assisted-by: Claude Opus 4.6
Signed-off-by: Sergio Correia <scorreia@redhat.com>
Comment thread src/luks/udisks2/test-token-to-jwe.c
Copy link
Copy Markdown
Collaborator

@sarroutbi sarroutbi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

@sarroutbi sarroutbi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sergio-correia sergio-correia merged commit 09fc885 into latchset:master Apr 20, 2026
12 checks passed
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.

2 participants