Repository navigation
App Attest step 1: CBOR, COSE_Key and WebAuthn authenticator-data decoders in .dag, claimed over a real Apple-issued attestation - #11970
Conversation
…thn authenticator-data decoders in .dag, claimed over a real Apple-issued attestation The first of the pure byte decoders the App Attest verifier needs (extdeps.apple.app_attest attestation_verification_from_implementation has no supplier on main). Three extdeps modules, each cited: extdeps.standards.rfc_8949 (strict CBOR: definite-length only, floats and reserved additional info refuse, integers beyond 2^53 refuse before the multiply, nesting bounded, unique text-key member read), extdeps.standards.rfc_9052 (COSE_Key EC2 P-256 ES256 -> SEC 1 point), extdeps.standards.webauthn_authenticator_data (the §6.1 layout, whole and 37-octet prefix). The fixture is a real attestation object and assertion Apple issued to a development build (veehaitch/devicecheck-appattest ios-14.4.yaml at cb26211f), transcribed as octets with its published facts; over it the decoders establish Apple's steps 4, 5, 6, 7 and 8 from real bytes. One upstream fact the sample surfaced: Apple's assertion authenticatorData is 37 octets with the AT flag set and nothing following, so assertions are read as the prefix, never the full layout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
a5530e9 to
4a45ee7
Compare
…ther than re-matching CborValue (review 69585) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…P-256 and P-384 as parameter rows, SHA-384, and the frontier retargeted to the decided shape extdeps.crypto.nist_prime_curve carries the a = -3 Jacobian group law, Shamir double-scalar ladder, partial public-key validation and ECDSA verification over a SUPPLIED digest, written once (the formulas #11645 landed for P-256, moved not rewritten). extdeps.crypto.nist_p256 is now its parameter row plus the SHA-256-bound verifier the device signature uses; the new extdeps.crypto.nist_p384 is the second row, consumed by Apple's chain step, whose two links are a P-384 key signing with SHA-256 and a P-384 key signing with SHA-384. extdeps.crypto.sha2 gains SHA-384 (the SHA-512 computation with its own initial state, truncated) over std.bitwise Word64, its constants derived from the definition rather than transcribed. P-256 semantics preserved by execution: the RFC 6979 sample signature verifies and the different-message control is false through the family fold (88 s / 86 s, 56M / 55M eval steps, peak 15.5 GiB), and n.G = infinity holds. P-384 established on real bytes: Apple's CA 1 and root keys are on the curve, a neighbouring point is not; the two chain-link verifications are enrolled and NOT executed here (at 17 limbs they exceed this container's memory), the same disposition as #11645's eight P-256 rows: a dedicated native gunbc test row is their executing evidence. gunbc.auth.approval_device_redemption ecdsa_verification_realization_frontier no longer names the host-Rust primitive the operator refused; it names the .dag readers landed by #11970/#11975/ this change, the verifier folds still owed, and the execution route decision (natively emitted handler once MachineWidth<N> reification lands; interpreter cost is the v1-performance row). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ture's ByteSize authority; the two guard-shadowed zero defaults (CBOR argument octets, authenticator-data octets) now refuse as located truncations Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review 69598 — both findings taken, in ff9a1e3: the COSE coordinate width is now derived from — sent from nimble-eagle-216 |
…rived offsets (no bare 32/33), the truncation refusal carries ByteSize, and cose_integer_at answers Int? rather than a fabricated 0 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review 69674 — all three taken, in 199f273: the §6.1 widths are — sent from nimble-eagle-216 |
…ively (no in-band Int a caller could name a seventh of); CborTruncated carries needed/available as ByteSize; the two sample rows step 1 does not read are deleted and the clientDataHash row names its consumer (step 2's nonce claim) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review 69692 — all three taken, in 2fdea11: — sent from nimble-eagle-216 |
…eyCoordinateNotAByteString (no zero-length measurement); the two TrailingOctets arms carry ByteSize; cbor_unsigned_value names its consumer (the verifier's category reader, #11989) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Review 69721 — all three taken, in 87539e5: — sent from nimble-eagle-216 |
Step 1 of the iOS approval-app plan (thread msg_8d2b7301; decision msg_54c92f2f: A terminal, B filed, proceed on 1/2/4 + P-384 authoring). The pure byte decoders the App Attest verifier needs, in
.dag, each an independently cited upstream module (DESIGN §3, external upstream decomposition):extdeps.standards.rfc_8949— CBOR, strict: definite-length only (indefinite refuses at its head naming the major type), major 7 with info 25..27 (floats) refuses, reserved info 28..30 refuses, integers ≥ 2^53 refuse before the multiply (the 64-bit host Int would otherwise overflow loudly first — found by the witness), nesting bounded at 16, one-document-consumes-all, unique text-key member read (duplicate key refuses, asjson_object_unique_memberdoes).extdeps.standards.rfc_9052— COSE_Key, exactly the EC2/P-256/ES256 shape, rendered as the SEC 1 uncompressed pointextdeps.crypto.nist_p256takes; duplicated labels refuse.extdeps.standards.webauthn_authenticator_data— WebAuthn L3 §6.1: whole structure (AT → attested credential incl. COSE key, ED → extensions, trailing refuses) and the 37-octet prefix.extdeps.apple.app_attest_sample_ios_14_4— a real attestation object + assertion Apple's service issued to a development build (veehaitch/devicecheck-appattestsrc/test/resources/ios-14.4.yaml@cb26211f, Apache-2.0), transcribed as octets (SHA-256 of both in the module) with the corpus's published facts (team id, bundle id, key id, clientDataHash, counter). Apple publishes no vector; this is the external authority for what the service emits.What is established, by execution
Over Apple's bytes (
test.claim.app_attest_sample_decode_witness_test): fmtapple-appattest; x5c = [761, 583]-octet DER; 3703-octet receipt; authData 164 octets with AT,appattestdevelopAAGUID (step 7), counter 0 (step 6), credentialId == key id (step 8),rpIdHash == SHA256(app_attest_app_id(team, bundle))(step 5, joinsextdeps.crypto.sha2),SHA256(COSE key as SEC 1) == key id(step 4). Assertion: 37-octet prefix, counter 1, 70-octet DER signature.Upstream fact the sample surfaced, now modeled: Apple's assertion
authenticatorDatais 37 octets with the AT flag (0x40) set and nothing following — it violates WebAuthn's own layout, so the full decoder refuses it as truncated at offset 37 and assertions are read bydecode_authenticator_data_prefix. Both arms are claimed so the prefix reader cannot be silently swapped for the full one.Chain facts read from the sample's DER (for step 3's sizing): leaf is P-256 signed
ecdsa-with-SHA256by a P-384 CA key; CA 1 → root is P-384 /ecdsa-with-SHA384(root PEM fetched from apple.com confirms secp384r1). So P-384 arithmetic is on the path for both chain links; SHA-384 for one.Receipt (exact head 4a45ee7, binary
/cargo-target/release/claim_batchsha256b763d4dd…e7cae1)Costs by
[witness]line: CBOR/COSE rows 60–3.3k eval steps; sample rows 2.2k–449k (the largest is SHA-256 of the 65-octet point). A first cut carried the fixture as base64 and paid ~3.7M steps per row on the transport encoding — that is why the fixture is octets.Mutation controls (each restored by reverse edit, positives beside them):
webauthn_authenticator_dataAT bitflags / 64→flags / 32:the_sample_auth_data_carries_apples_factsFAIL,the_sample_attestation_decodes_to_apples_shapePASS.rfc_8949negative0 - 1 - arg→0 - arg:appendix_a_negative_decodeFAIL,appendix_a_map_decodePASS.Parse:
v1_src_dag_parseclean on all seven files (the only errors it prints are pre-existing indag/test/claim/fabric/fabric_storage_wire_witness_test.dag, on main). Bare-name sweep: six helper names collided with existing corpus declarations (ascii,entry,finish,refuses,decodes_to,well_formed) and were renamed before commit.Consumption (§3c), stated honestly
rfc_8949is consumed bywebauthn_authenticator_data; all three decoders and the sample are consumed by the witnesses. Their production consumer — the fold that suppliesattestation_verification_from_implementation/assertion_verification_from_implementation— is step 3 of the plan (declared frontier already on main:gunbc.auth.approval_device_redemptionecdsa_verification_realization_frontier, which names "CBOR decode, X.509 chain…" as the missing pieces; this PR lands the CBOR half). Step 2 (ASN.1 DER + RFC 5280 profile + pinned Apple root) follows as its own PR.CI green is not evidence for these product-layer modules (required lanes do not resolve them); the receipt above is.
🤖 Generated with Claude Code