Skip to content

Additional 18013-5 checks - #1976

Merged
davidz25 merged 4 commits into
mainfrom
addtl-checks
Sep 3, 2026
Merged

Additional 18013-5 checks#1976
davidz25 merged 4 commits into
mainfrom
addtl-checks

Conversation

@davidz25

@davidz25 davidz25 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #1975.

According to ISO/IEC 18013-5:2021 clause 9.3.3.4, if any data elements
are returned as part of DeviceSigned, the verifier must verify that all
those data elements or their namespace are included in the keyAuthorizations
map in the DeviceKeyInfo map in the MSO:

- In `MdocDocument`, update `verify()` to iterate through all returned
  data elements in `deviceNamespaces.data` and verify that each data
  element is authorized either by its namespace being listed in
  `MobileSecurityObject.deviceKeyAuthorizedNamespaces` or by the data
  element identifier being present in
  `MobileSecurityObject.deviceKeyAuthorizedDataElements`. Throw an
  `IllegalStateException` if any data element is unauthorized.
- In `DeviceResponse`, update KDoc for `verify()` to document this check.
- In `DocumentType`, add optional parameters `deviceKeyAuthorizedNamespaces`
  and `deviceKeyAuthorizedDataElements` to
  `createMdocCredentialWithSampleData()` to allow configuring device key
  authorizations for sample credentials.
- In `DeviceResponseGeneratorTest`, configure authorized namespaces in
  `provisionDocument()` for tests asserting `DeviceSigned` presentment.
- In `DeviceResponseTest`, add unit tests covering authorized namespaces,
  authorized data elements, unauthorized namespaces, unauthorized data
  elements, missing key authorizations, and roundtrip parsing.
- In `samples/SwiftTestApp`, update calls to
  `createMdocCredentialWithSampleData()` for the new parameters.

Fixes #1975.

Test: Ran ./gradlew :multipaz:jvmTest
Test: Ran ./gradlew detekt
Test: Tested manually in SwiftTestApp on iOS

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
According to ISO/IEC 18013-5 Second Edition clause 12.8 (Validation and
inspection procedures), implement additional checks for issuer data
authentication and certificate validation:

- In `MdocDocument.verify()`, verify that `mso.signedAt` falls within the
  leaf Document Signer (DS) certificate validity period (`notBefore` to
  `notAfter`).
- In `MdocDocument.verify()`, `DeviceResponse.verify()`, and
  `DeviceResponse.verifySingleDoc()`, add optional parameter
  `rejectIfValidUntilAfterNotAfter: Boolean = false` to optionally reject
  responses where `mso.validUntil` exceeds the DS certificate `notAfter`
  timestamp (discretionary for readers per 12.8.1 step 5).
- In `X500Name`, add convenience properties `countryName`,
  `stateOrProvinceName`, and `commonName`.
- In `TrustManagerUtil.validateCertificationTrustPath()`, verify that the
  leaf certificate's `countryName` matches the IACA certificate's
  `countryName`, and that `stateOrProvinceName` matches if present in both
  certificates when verifying an IACA/issuer chain (clause 12.8.3).
- In `TrustPoint`, add `isIaca` and `docTypes` properties to store whether
  the trust point represents an IACA and the document types authorized by
  a VICAL, and in `TrustResult` include `authorizedDocTypes`.
- In `TrustManagerInterface.verify()`, add `docType: String? = null`
  parameter (with backward-compatible overload) and update implementations
  (`TrustManager`, `ConfigurableTrustManager`, `VicalTrustManager`,
  `RicalTrustManager`, `CompositeTrustManager`, and `TrustManagerUtil`)
  to verify that the presented document type is authorized by the matching
  VICAL (clause 12.8.1).
- In `DeviceResponseTest`, add unit tests for `signedAt` before/after DS cert
  validity and `validUntil` after `notAfter`.
- In `TrustManagerTest`, add unit tests for IACA subject DN matching,
  VICAL document type authorization, and Reader CA cross-border issuance.

Fixes #1975.

Test: Ran ./gradlew :multipaz:jvmTest
Test: Ran ./gradlew detekt

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
When a device request query cannot be satisfied due to missing data
elements or namespaces in candidate credentials, include specific details
about the unsatisfied data elements and namespaces in the exception
message instead of a generic failure string:

- In `DeviceRequest`, track missing data elements and namespaces when
  checking logical requirements against candidate credentials in
  `findBestMatchingClaims()`. If any requirement cannot be satisfied
  (neither base claim nor alternatives present), record the specific data
  element and namespace.
- In `DeviceRequest.execute()`, append the failure specifics to the
  `Iso18015ResponseException` message for both 18013-5:2021 requests and
  Second Edition use cases.
- In `Iso18013TestPrivacyPreservingAgeRequest`, update `mdlWithNoAgeInfo`
  to verify the specific missing data element exception message.
- In `Iso18013TestSingleMdlQuery`, add unit tests verifying specific
  exception messages when a single data element is missing, multiple data
  elements are missing, an element in a custom namespace is missing, and
  when a mandatory use case fails due to a missing data element.

Fixes #1975.

Test: Ran ./gradlew :multipaz:jvmTest
Test: Ran ./gradlew detekt

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
Add support for lenient claim matching on version 1.0 requests, configure
version selection in the verifier server, and ensure reader root
certificates are excluded from reader authentication COSE headers:

- In `DeviceRequest.execute()`, implement lenient matching for version 1.0
  requests: deem a request satisfied if at least one requested data element
  is present in the credential. For version 1.1+ requests, maintain strict
  matching requiring all requested data elements (or alternatives) to be
  present.
- In `DeviceRequest.Builder`, add support for targeting version 1.0 by
  omitting second-edition features (`requestInfo` in `DocRequest` and
  `deviceRequestInfo`).
- In `DeviceRequest.Builder.addDocRequest()` and
  `DeviceRequest.Builder.addReaderAuthAll()`, encode `x5chain` using
  `X509CertChain.toCoseX5Chain(excludeRoot = true)` so self-signed root CA
  certificates are omitted from the COSE header parameter per RFC 9360 and
  ISO/IEC 18013-5. Update KDoc documentation accordingly.
- In `buildDeviceRequestFromDcql()`, add `version: String? = null` parameter
  and pass it to `DeviceRequest.Builder`.
- In Credman Wasm matcher (`Request.cpp`, `dcql.cpp`, `dcql.h`), update
  matching logic so version 1.0 queries succeed if at least one requested
  claim matches, while version 1.1 queries require all requested claims to
  match. Rebuild `identitycredentialmatcher.wasm`.
- In `VerificationUtil`, add optional `deviceRequestVersion: String? = null`
  to `generateDcRequestMdoc()`, `generateDcRequestDcql()`,
  `generateDcRequestSdJwt()`, `generateSingleRequest()`, and
  `generateSingleRequestDcql()`. When `null`, automatically determine the
  version to use.
- In `multipaz-verifier-server`, add UI combo box in `index.html` and
  `verifier.js` to select DeviceRequest version 1.1 or 1.0 for ISO 18013-7
  Annex A and Annex C protocols, and handle `deviceRequestVersion` in
  `verifier.kt`.
- In `Iso18013TestSingleMdlQuery`, add unit tests for version 1.0 lenient
  claim matching versus version 1.1 strict matching.
- In `MatcherTest`, add instrumented tests for Credman matcher version 1.0
  and 1.1 behavior.
- In `DeviceRequestTest`, add unit test verifying exclusion of root
  certificates from `x5chain` in `readerAuth` and `readerAuthAll`.
- In `VerificationUtilTest`, add unit tests verifying version 1.0, 1.1, and
  default version generation for mdoc and DCQL requests.

Fixes #1975.

Test: Ran ./gradlew detektMetadataCommonMain
Test: Ran ./gradlew :multipaz:jvmTest
Test: Ran ./gradlew :multipaz-verifier-server:test
Test: Ran ./gradlew :multipaz-verifier-server:assemble
Test: Ran ./gradlew :multipaz-dcapi:connectedDebugAndroidTest (65 tests passed)
Test: Tested manually in multipaz-verifier-server web UI

Signed-off-by: David Zeuthen <zeuthen@gmail.com>
@davidz25
davidz25 merged commit d88d0d1 into main Sep 3, 2026
4 checks passed
@davidz25
davidz25 deleted the addtl-checks branch September 3, 2026 15:04
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.

Enhance ISO/IEC 18013-5 verification checks, Second Edition inspection procedures, and version compatibility

1 participant