Skip to content

feat(webauthn): largeBlob write and delete#261

Merged
AlfioEmanueleFresta merged 4 commits into
masterfrom
feat/webauthn-largeblob-write
Jun 7, 2026
Merged

feat(webauthn): largeBlob write and delete#261
AlfioEmanueleFresta merged 4 commits into
masterfrom
feat/webauthn-largeblob-write

Conversation

@AlfioEmanueleFresta

Copy link
Copy Markdown
Member

Adds the WebAuthn L3 largeBlob write extension and a libwebauthn-side delete operation, on top of CTAP 2.2 authenticatorLargeBlobs.

After an assertion yields the per-credential key, the platform fetches the on-authenticator blob array, replaces or erases the entry belonging to this credential, and re-uploads the array in chunks. Other credentials' blobs and any unknown fields are preserved byte for byte. The lbw permission is negotiated into the get-assertion token so a single user verification covers the write. Unprotected authenticators are written without auth params.

Write and delete failures are non-fatal and surface as written=false rather than failing the assertion.

Stacked on #206 (largeBlob read). Merge that first. Supersedes #224.

Base automatically changed from feat/webauthn-largeblob-storage to master June 7, 2026 21:18
Add new_set_first and new_set_continuation per CTAP 2.2 §6.10.2:
length is present only when offset is zero, omitted otherwise.
Both take Option<(auth_param, protocol)> so unprotected
authenticators can issue the command without pinUvAuthParam.
Implements WebAuthn L3 §10.1.5 write and a libwebauthn-side delete
on top of CTAP 2.2 §6.10.6 update-or-erase. The platform fetches the
existing large-blob array, drops any entry that decrypts under the
credential's largeBlobKey, optionally appends a fresh encrypted entry,
and re-uploads the canonical CBOR array with a fresh SHA-256 trailer.
Foreign entries (different key, malformed, unknown fields) are
preserved byte-for-byte per the §6.10.2 platform contract.

Upload is chunked per maxFragmentLength with pinUvAuthParam computed
as authenticate(token, 32*0xff || 0x0c 0x00 || u32_le(offset)
|| SHA-256(set)) per §6.10.2. The Ctap2GetAssertionRequest now ORs
LARGE_BLOB_WRITE into its permissions when write or delete is
requested so user_verification negotiates a token covering the lbw
permission.

To keep PIN-protected devices working under UV=Discouraged, the
Ctap2UserVerifiableRequest trait gains needs_pin_uv_auth_token,
which suppresses the OnlyForSharedSecret downgrade in
user_verification. Unprotected authenticators continue to accept the
write without auth params per spec line 137.

Delete with no matching entry returns LargeBlobError::NoMatch
(written=false), matching the strict §6.10.6 'Return an error' branch
at line 303.
Exercises the WebAuthn write/delete extensions against the virt
authenticator end-to-end:
- write then read returns the planted bytes
- second write replaces the first entry
- delete after write removes the entry; subsequent read returns no blob
- delete with no prior entry reports written=false
Preserve foreign largeBlobArray entries by their exact bytes on
read-modify-write rather than re-serialising them, which also drops a
redundant re-encode of the new entry. Treat a valid-trailer but
unparseable array as a fail-safe error rather than clobbering it. Satisfy
the production clippy::indexing_slicing denies in the write path. Refuse
the U2F downgrade for largeBlob write and delete.

Adds tests for nonce uniqueness across writes, the pinUvAuthParam
protocol-1 path, the JSON write input, the PIN-protected write token
ceremony under UV=Discouraged, foreign-blob survival across write and
delete, the single-allowCredential guard, and shrink-on-replace.
@AlfioEmanueleFresta AlfioEmanueleFresta force-pushed the feat/webauthn-largeblob-write branch from c18ac78 to 6799ed6 Compare June 7, 2026 21:21
@AlfioEmanueleFresta AlfioEmanueleFresta merged commit 60d8d95 into master Jun 7, 2026
5 checks passed
@AlfioEmanueleFresta AlfioEmanueleFresta deleted the feat/webauthn-largeblob-write branch June 7, 2026 21: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.

1 participant