Skip to content
spruceidPublic

About

ISO/IEC 18013-5 Rust implementation

Topics

Resources

Stars

16 stars

Watchers

14 watching

Forks

Repository files navigation

isomdl

ISO/IEC DIS 18013-5 mDL implementation in Rust.

It is intended to be used in creating apps for devices and readers that can interact with each other to exchange mDL data.

CLI tool

This crate contains a CLI tool. Run the --help command to see what actions you can perform.

cargo run -- --help

For example, you can get the namespaces and elements defined in an mDL:

cat test/stringified-mdl.txt | cargo run -- get-namespaces -

Library

Here are some examples on how to use the library. You can see more in tests and read about in the dedicated README.

Examples

Simulated device and reader interaction

This example demonstrates a simulated device and reader interaction.
The reader requests the age_over_21 element, and the device responds with that value.

sequenceDiagram
    autonumber
    Note over Device: Initialize session
    Device ->> Device: Create QR Code Engagement
    Device -) + Reader: Send QR Code
    Reader ->> - Reader: Establish Session
    Reader -) + Device: Request age_over_21
    Device -)- Reader: Send age_over_21
    Reader ->> Reader: Process age_over_21
    Note over Device, Reader: Session finished
Loading

The flow of the interaction

  1. Device initialization and engagement:
    • The device creates a QR code containing DeviceEngagement data, which includes its public key.
    • Internally:
      • The device initializes with the mDL data, private key, and public key.
  2. Reader processing QR code and requesting needed fields:
    • The reader processes the QR code and creates a request for the age_over_21 element.
    • Internally:
      • Generates its private and public keys.
      • Initiates a key exchange, and generates the session keys.
      • The request is encrypted with the reader's session key.
  3. Device accepting request and responding:
    • The device receives the request and creates a response with the age_over_21 element.
    • Internally:
      • Initiates the key exchange, and generates the session keys.
      • Decrypts the request with the reader's session key.
      • Parse and validate it creating error response if needed.
      • The response is encrypted with the device's session key.
  4. Reader Processing mDL data:
    • The reader processes the response and prints the value of the age_over_21 element.
Device perspective

There are several states through which the device goes during the interaction:

stateDiagram
    state Device {
        [*] --> SessionManagerInit: initialise
        SessionManagerInit --> SessionManagerEngaged: qr_engagement
        SessionManagerEngaged --> SessionManager: process_session_establishment
    }

    state SessionManagerInit {
        [*] --> [*]
    }

    state SessionManagerEngaged {
        [*] --> [*]
    }

    state Reader {
        [*] --> [*]
    }

    state SessionManager {
        [*] --> AwaitingRequest
        AwaitingRequest --> Signing: prepare_response
        Signing --> Signing: get_next_signature_payload
        Signing --> ReadyToRespond: submit_next_signature
        ReadyToRespond --> AwaitingRequest: retrieve_response
        AwaitingRequest --> Signing: handle_request
    }

    User --> Device
    SessionManagerInit --> Reader: qr_engagement
    Reader --> SessionManagerEngaged: establish_session
    ReadyToRespond --> Reader: handle_response
Loading
Reader perspective

From the reader's perspective, the flow is simpler:

stateDiagram
    state Device {
        [*] --> [*]
    }

    state Reader {
        SessionManager --> SessionManager: handle_response
    }

    User --> Device
    Device --> Reader: qr_engagement
    Reader --> Device: establish_session
    Device --> Reader
    Reader --> Device: new_request
Loading

Example

You can see the full example in simulated_device_and_reader and a version that uses State pattern, Arc and Mutex simulated_device_and_reader.

Requesting and validating credentials

A reader asks for one or more credentials, each with its own doc type, and every document in the response is validated on its own — they are cryptographically independent, and ISO/IEC 18013-5 permits several, including two of the same doc type.

let (mut reader, request, _ble_ident) = reader::SessionManager::establish_session(
    reader::Handover::QR(qr),
    NonEmptyVec::new(ItemsRequest::mdl(namespaces)),
    trust_anchors,
)?;

let outcome = reader
    .handle_response(&response, &AnyDocType(MdocProfile::MDL), &fetcher)
    .await;

ResponseValidationOutcome splits the response four ways: documents passed every check, failed were evaluated and did not, rejected were never asked for and so never validated, and errors says why the response as a whole is not wholly good. Check warnings as well — a warning is a check that could not be completed, so DocumentWarning::Revocation means revocation status is unknown, not clear. See the rustdoc on those types for the full contract, and end_to_end.rs for worked exchanges.

Credentials other than the mDL

Annex B's certificate structure applies to any mdoc, but its OIDs are mDL-specific — the DIS of the second edition says Annex B does not apply when reading other mdoc based documents. MdocProfile supplies the right ones; MDL, AAMVA_MDL, ISO_23220 and EUDI_PID ship. AnyDocType applies one profile to everything, a BTreeMap<String, MdocProfile> selects per doc type and refuses what it does not cover.

A credential whose PKI differs by more than its OIDs needs a CertificateProfile implementation instead — a chain with intermediate CAs, certificates carrying no mdoc key purpose, revocation published somewhere other than a CRL. EuAgeVerificationProfile ships as one such: EU age verification wants an ETSI EN 319 411-1 NCP signer trusted through a Trusted List, and revokes out of band, so a clean outcome from it does not mean "not revoked".

Worked examples of both: an_eudi_pid_presents_end_to_end and a_custom_profile_validates_through_the_reader_api, and a_custom_profile_can_express_eu_age_verification.

About

ISO/IEC 18013-5 Rust implementation

Topics

Resources

Stars

16 stars

Watchers

14 watching

Forks

Releases

Packages

Used by

Contributors

Languages