feat(webauthn): largeBlob write and delete#224
Draft
AlfioEmanueleFresta wants to merge 3 commits into
Draft
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the WebAuthn L3 §10.1.5
largeBlob.writeextension and a libwebauthn-side delete operation, layered on top of CTAP 2.2 §6.10.6. The platform fetches the existing on-authenticator array, replaces or erases the entry that decrypts under the credential'slargeBlobKey, and re-uploads the canonical CBOR array via chunkedauthenticatorLargeBlobs(set). Foreign entries (other credentials' blobs, unknown CBOR fields) are preserved byte-for-byte per the §6.10.2 platform contract.Stacked on #206 (read leg). Merge that first.
Scope
Write(Vec<u8>)andDeletevariants on the get-assertion largeBlob extension inputwrittenflag on the assertion's largeBlob outputpinUvAuthParamfor each chunk derived per §6.10.2:authenticate(token, 32×0xff || h'0c00' || u32_le(offset) || SHA-256(set))lbwpermission negotiated into the get-assertion token when write or delete is requested, so one PIN/UV ceremony covers both operations. Unprotected authenticators continue to accept the write without auth params per §6.10.2 line 137read+writetogether returns a NotSupportedError, and write/delete require exactly oneallowCredentialsentrywritten=false, matching the strict §6.10.6 "return an error" branchTests
pinUvAuthParambyte construction, AAD format, the read-modify-write loop, and the byte-fingerprint of the canonical empty array (h'8076be8b528d0075f7aae98d6fa57a6d3c')Follow-ups
written=falserather than forcing a PIN prompt