Skip to content

ISO/IEC 18013-5 mdoc support (mso_mdoc) + EU Age Verification profile compliance #562

@DibranMulder

Description

@DibranMulder

ISO/IEC 18013-5 mdoc support + EU AV profile compliance

Tracking issue for landing the mso_mdoc credential format in irmago — issuance to the wallet via OpenID4VCI and disclosure via OpenID4VP (DCQL) — and for becoming compliant with the EU Age Verification (AV) profile, including making go-passport-issuer an AV Attestation Provider issuing proof-of-age mdocs over OpenID4VCI.

Plans (PR #570):

  • docs/mdoc-implementation-plan.md — mdoc in irmago (milestones M1–M7)
  • docs/av-profile-compliance-plan.md — cross-check against the EU AV technical specification / Annex A AV profile, irmago deltas (incl. milestone M8), and the go-passport-issuer phases (P1–P6)

Reference implementation: multipaz.

Relevant specs

  • ISO/IEC 18013-5:2021 — mdoc data model, MSO, DeviceResponse, selective disclosure
  • ISO/IEC TS 18013-7 — mdoc over OpenID4VP and the W3C Digital Credentials API (Annex C)
  • OpenID4VCI / OpenID4VP — mso_mdoc format, DCQL, vp_token encoding
  • EU Age Verification profile (Annex A): docType/namespace eu.europa.ec.av.1, age_over_NN boolean claims only, ES256/P-256, both OID4VCI grant types with PKCE S256, JWT proofs with batch issuance (recommended size 30), single-use attestations ≤ ~3 months, no revocation, av:// invocation scheme; presentation primarily via the W3C Digital Credentials API (org-iso-mdoc, HPKE-encrypted responses per RFC 9180), with unsigned-request OpenID4VP (direct_post, client-id scheme redirect_uri) as fallback
  • RFC 9052/9053 (COSE), RFC 8949 (CBOR), RFC 9180 (HPKE), RFC 7636 (PKCE)

Scope

irmago (wallet/holder side):

  • Receiving mso_mdoc credentials via OpenID4VCI (pre-authorized + authorization code flows, batch issuance), verified against trust anchors before storage.
  • Storing mdoc credentials and device keys alongside SD-JWT VCs.
  • Answering DCQL mso_mdoc queries with a DeviceResponse in a vp_token (direct_post and direct_post.jwt), selective disclosure, deviceSignature device auth.
  • AV profile deltas: Digital Credentials API presentation (M8), unsigned OpenID4VP requests with redirect_uri client-id scheme, MSO timestamp-precision truncation, av:// scheme handling, ETSI TS 119 612 trusted-list support.
  • Enough issuer/verifier-side mdoc code to build fixtures and run hermetic end-to-end tests in-process.

go-passport-issuer (AV Attestation Provider, sub-issues P1–P6):

  • Mint eu.europa.ec.av.1 proof-of-age mdocs (only age_over_NN claims) from ICAO 9303-validated documents, reusing irmago's mdoc building blocks.
  • Full OpenID4VCI issuer: metadata, token endpoint (pre-authorized code + authorization code, PKCE S256), nonce + credential endpoints with JWT-proofs batch issuance, av:// credential offers.
  • AV trust & ops: ETSI EN 319 411-1 (NCP) document signer cert / IACA, registration on the AV trusted list, privacy review (data minimisation, unlinkability).
  • Interop with the AV reference implementation; the IRMA issuance path remains.

Out of scope (for now):

  • deviceMac device auth, proximity flows (BLE/NFC device engagement, session encryption)
  • ZK presentations (longfellow-zk; SHOULD in the AV profile — tracked as a possible M9 once the profile hardens)
  • mdoc revocation/status lists (explicitly not required by the AV profile)

Key design decisions

  1. Add fxamacker/cbor/v2 and veraison/go-cose; COSE_Key (and later COSE_Mac0) implemented in-repo on top of cbor/v2.
  2. New self-contained package eudi/credentials/mdoc/, sibling of sdjwtvc/.
  3. Reuse the existing holder-binding key machinery (ECDSA P-256, encrypted storage, one key per batch instance) for mdoc device keys.
  4. Extend DcqlCredentialQueryHandler.PrepareDisclosure to take a DisclosureContext — the only cross-format interface change required.
  5. Storage follows the existing polymorphic-format TODO in eudi/storage/db/models/credentials.go.
  6. Handover construction (OpenID4VPHandover / DC-API handover) isolated in one function to absorb spec-draft churn.

Milestones

Each milestone is independently mergeable, fully covered by automated tests, and must not regress existing SD-JWT VC / idemix flows. See sub-issues (irmago M1–M8, go-passport-issuer P1–P6).

irmago:            M1 → M2 → M3 → M4 ─┬→ M5 (OID4VCI) ──┬→ M7 → (M8 DC API)
                                      └→ M6 (OID4VP) ───┘
go-passport-issuer: P1 (needs M3) → P2 (needs M5 as test harness) → P3 → P5 → P6
                                                        └→ P4 (parallel with P3)

Risks / open questions

  • OpenID4VP draft alignment: the handover structure changed between drafts; Annex A pins neither the OID4VCI nor OID4VP draft and AP metadata is "TBD" — keep handover construction isolated and AP metadata config-driven.
  • Device-binding ambiguity in the AV profile: Annex A marks device-bound attestations out of scope yet mandates JWT proofs; if AV reference attestations carry no device key, M2/M6 must tolerate MSOs without deviceKeyInfo — confirm early during interop.
  • cbor v1/v2 coexistence: legacy v1 usage (revocation) should eventually migrate, out of scope here.
  • go-cose API fit: if x5chain or raw R||S handling fights us, fall back to a minimal in-repo COSE_Sign1; decide during M1.
  • Claims projection fidelity: stable JSON mapping for CBOR element values (tdate, full-date, binary); DCQL value matching must follow OpenID4VP rules for non-string values (AV uses boolean claims).
  • Trusted-list operational dependency: AV trusted-list registration is a process with the Commission — start early; test lists exist for development.
  • Python EUDI issuer mdoc config: enabling the mdoc PID variant needs IACA/DS certificate config in testdata/eudi-pid-issuer-py/; budget for this in M5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementgoPull requests that update go code
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions