Issuance of Wallet Instance Attestation (WIA)¶
This flow describes the process of issuing a wallet attestation (WIA) as introduced here in the blueprint.
Design Decisions¶
In the wallet attestation process, the WI establishes a long-term authentication key pair for a particular Credential Issuer. This key pair is attested by the WB within the Wallet Instance Attestation (WIA), that attests to the security posture of the WI. The WIA contains a Status List entry, that the Credential Issuer may use to verify the security posture of the Wallet Instance in the future. The WIA may be revoked if:
- the user revoked its WI, e.g. because the user lost its device
- the MDVM revoked its WI, e.g. because the mobile device has a major vulnerability
The Wallet Instance generates a hardware-bound key pair on the mobile device and transmits the public key to the Wallet Backend. The key generation must utilize the most secure key store available on the mobile device, such as a Secure Element, StrongBox, SecureEnclave or TEE. A proof of possession for the private key is done by signing the challenge.
The Wallet Provider Backend (WB) verifies the provided MDVM Token (see MDVM flows for details) and that performs additional checks on vulnerability management and user-initiated revocation (see wallet revocation for details). In return, the WB issues a Wallet Instance Attestation (wb_wia), that attests the integrity and authenticity of the Wallet Instance, bound to the public key (wi_wia_pubk). The wb_wia is a JWT as defined in attestation-based client authentication, using x509 certificate as trust mechanism to sign the WIA.
Data Flow¶
This section described the data flow of the Wallet Registration in a sequence diagram and a more detailed table. Artifacts in italics are further explained in the data register chapter
Sequence Diagram¶
The sequence diagram contains two flows marked as alternatives when they diverge:
1) In the initial WIA issuance operation, the WI requests a Wallet Instance Attestation for the very first interaction with a new Credential Issuer. The green section describes steps that are only relevant for this flow. 2) In the WIA renewal operation, the WI requests to get an updated WIA for a Credential Issuer that it already interacted with in the past. The pink section describes steps that are only relevant for this flow.
Detailed Description¶
| No | Description |
|---|---|
| 001 | The WI determines if its most recent mdvm_token is still valid. If the mdvm_token is not up-to-date, the WI may fetch a fresh one from the MDVM endpoint using the renewal flow for either Android or iOS. |
| 002 - 004 | The WI requests a challenge from the WB challenge endpoint using an HTTP POST request, the request is unauthenticated. The WB generates a JSON structure containing a random nonce and a timestamp of the current time and MACs it using a symmetric key (wb_mac_symk) as a JSON Web Token (JWT), the resulting structure is the wb_auth_challenge. The WB responds to the WI with the wb_auth_challenge in the HTTP payload. The WI uses the challenge as a transparent string and does not evaluate the JWT claims. The WB does not store the challenge after creation, thus the operation is stateless. |
| 005 | The WI generates a a new hardware-bound key pair (wi_wia_prvk,wi_wia_pubk) which is used as the client attestation key for the wallet attestation (WIA). The WI must leverage the most secure, local key storage available, i.e. a Secure Element, StrongBox, SecureEnclave or TEE. The key must have sufficient security, information on algorithms and key lengths can be found in the cryptography chapter. |
| 006 | The WI performs a look-up in its internal mapping of Credential Issuer identifier to WIA Status List entry wb_wia_status (consisting of uri and idx). If the WI had a previous interaction with this Credential Issuer it would have stored such a mapping in Step 022. |
| 007 | Step 007 only occurs in the WIA renewal operation If a WIA has been used with the Credential Issuer before the WI finds an entry in the mapping and sets the corresponding Status List entry wb_wia_status as an additional input wi_wb_operation_params for the request wi_wb_auth_pop. |
| 008 | The WI computes a proof of possession by signing the payload of wb_wi_id for identification, wb_auth_challenge for freshness and to enable replay protection, the mdvm_token to ensure authenticity and integrity of the WI, the client attestation public key wi_wia_pubk and potentially additional wi_wb_operation_params containing the wb_wia_status with
|
| 009 | The WI requests the WB to issue a WIA by sending the proof of possession (wi_wb_auth_pop) to the WIA endpoint. The request is authenticated. |
| 010 | The WB verifies the self-contained wb_auth_challenge included in the wi_wb_auth_pop using its symmetric key (wb_mac_symk) and validating that the timestamp is within a valid time interval of 0 minute to +5 minutes. This step ensures replay protection beyond the valid time interval of the challenge. |
| 011 - 014 | The WB validates the security posture of the WI by verifying the mdvm_token with mdvm_attestation_pubk and checks that it is still valid. The WB has a trusted, out-of-band mechanism towards the MDVM to fetch the valid mdvm_attestation_pubk. The WB fetches the public key for the possession factor wi_wb_auth_pubk from the database using the provided account identifier wb_wi_id included in wi_wb_auth_pop. The WB verifies the signature of the received proof of possession (wi_wb_auth_pop) for the WI's possession factor using wi_mdvm_auth_pubk from the mdvm_token. Lastly, the WB verifies that the used key wi_mdvm_auth_pubk is the same in mdvm_token and in the database. The database lookup is not subject to prevention of distributed denial of service attacks, as these attacks need to be mitigated further up in the infrastructure layer. |
| 015 | The WB verifies the second signature of proof of possession wi_wb_auth_pop using using the included wi_wia_pubk. |
| 016 | The WB queries the revocation state wb_wi_state from its database to validate that the user did not revoke its WI. If the state is not "VALID", the request is aborted. This step ensures that a revoked WI cannot receive new WIAs to prevent further issuances. |
| 017 - 018 | Steps 017 - 018 only occur in the initial WIA issuance operation The WB chooses a new, un-used Status List entry wb_wia_status for the WIA to be created. The WB then stores the new wb_wia_status for this particular WI account in the database. |
| 019 | Step 019 only occurs in the WIA renewal operation |
| 020 | The WB generates a Wallet Instance Attestation wb_wia by signing the provided public key wi_wia_pubk and the status entry wb_wia_status using its wb_wia_auth_prvk using PKCS#11 function C_SignInit and C_Sign. As the rwscd_wte_auth_prvk is a long-term key stored in the HSM, it does not need to be imported or destroyed. The resulting wb_wia assures the Issuer that the corresponding Wallet Instance is a valid client of the wallet solution, the particular WI's security posture is attested by the WB and that the user did not revoke its WI. The Issuer later fetches the wb_wia_auth_pubk from a trust list to verify the wb_wia. |
| 021 | The WB returns the Wallet Instance Attestations wb_wia to the WI. |
| 022 | Step 021 only occurs in the initial WIA issuance operation |
WB setup¶
The WB uses a Hardware Security Module (HSM) for the following use cases:
- wb_wia_auth_prvk (used to sign the Wallet Instance Attestations)
The WB and the HSM uses mutual TLS to encrypt and authenticate their communication. Additionally, the PKCS#11 C_Login operation is used to authenticate to a specific HSM partition. The WB uses PKCS#11 as the API to send requests to the HSM.
WB Account database¶
The WB account database stores the necessary information for each Wallet Instance's account:
- wb_wi_id
- wi_mdvm_auth_pubk
- Hash(wb_wi_revocation_secret)
- wb_wi_state (VALID, PENDING_WIA_REVOCATION, PENDING_APP_REVOCATION, REVOKED)
- list of wb_wia_status
Access to the database is secured by mutual TLS to encrypt and authenticate communication to the WB.
Wallet Challenge JWT¶
Defined in Wallet Registration
Proof of Possession JWT for Authentication¶
The wi_wb_auth_pop is a possession-based authentication factor of the Wallet App, that creates a proof of the wi_mdvm_auth_prvk over the wb_auth_challenge.
The wi_wb_auth_pop contains:
- JOSE Header
typas recommended by JWT BCP - JOSE Header
algindicating ECDSA NIST P-256 - JWT Claim
wb_wi_idcontaining the serialized wb_wi_id - JWT Claim
wb_auth_challengecontaining the serialized wb_auth_challenge - JWT Claim
mdvm_tokencontaining the serialized mdvm_token - JWT Claim
wi_wia_pubkcontaining the serialized wi_wia_pubk - JWT Claim
audreferencing the URL of the Wallet Provider Backend
Note: There is no jti parameter for potential enhanced replay protection, as we can reuse the wb_auth_challenge for this purpose. There is also no iat or exp parameter, because the wb_auth_challenge already includes a trusted timestamp.
There is also no iat or exp parameter, which is added by the WI, because the wb_auth_challenge already includes a trusted timestamp.
Below is a non-normative example of a wi_wb_auth_pop:
Protected headers:
Payload:{
"wb_wi_id": "3e8ba9be-78d9-4ed3-996a-a9d4d72ce414",
"wb_auth_challenge": "eyJ0eXAiOiJ3Yi1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzgzMTQ4NzQsIm5vbmNlIjoiZmEwYTMxMGUtOTFkMi00NjFjLWJhMDAtY2MzNWE5OTVmMTY2IiwiaWF0IjoxNzM4MzExMjc0fQ.7QpBVKvwuukioYhLX402ay-DwTv5H3x-hhovev72i58",
"mdvm_token": "...",
"wi_wia_pubk": {
"kty": "EC",
"crv": "P-256",
"x": "32jtyqhBGxKxqeihaRsmW449oB9hcMUSgNCxDjHfADo",
"y": "3ARvwMghvfz7zAcGEdwQj2h5DQU64BezdaSthn7qJzk"
}
"aud": "https://wallet-provider-backend.eudi-wallet.de"
}
Signed by wi_mdvm_auth_prvk
Wallet Instance Attestation (WIA)¶
The wb_wia is a signed attestation of the Wallet Provider backend, attesting to the validity of the Wallet Instance towards Issuers and Relying Parties. The format is described in Section 5.1 of attestation-based client authentication.
In accordance to the rules defined in the draft, the wb_wia contains:
- JOSE Header
typas recommended by JWT BCP - JOSE Header
algindicating ECDSA NIST P-256 - JOSE Header
x5ccontaining the x509 certificate chain of the Wallet Provider - JWT Claim
sub: referencing the client_id of the Wallet Provider Backend - JWT Claim
exp: current time + expiration time interval, indicating the expiration data of the WIA - JWT Claim
cnf: containing the serialized wi_wia_pubk - JWT Claim
iat: current time, indicating the issuance date of the WIA (optional) - JWT Claim
status: status information about the authenticity and integrity of the Wallet Instance- JWT Claim
status_list: status information as a Status List- JWT Claim
uri: URI that links to the Status List Token - JWT Claim
idx: index within the Status List Token that represents the status of the WI
- JWT Claim
- JWT Claim
Below is a non-normative example of a wb_wia:
Protected headers:
{
"typ": "oauth-client-attestation+jwt",
"alg": "ES256",
"x5c": [
"MIIBETCBuQIJAM6k5TM9MgHEMAkGByqGSM49BAEwEjEQMA4GA1UEAwwHdGVzdC5kZTAeFw0yNDExMTExMjMwMTRaFw0yNTExMTExMjMwMTRaMBIxEDAOBgNVBAMMB3Rlc3QuZGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATQivHxcyv56XIfjt6EeyekabQ44oXSvplQXwE42c5SKheiZyhKfjhATMdpNQKV+2WnNX28Dwlv/mBQkA2pPe98MAkGByqGSM49BAEDSAAwRQIgcn7PP74vJ82nUxVQA4nt++IzWK+xYX2jGe9oh/5R9CICIQCsCjry+BL5biHKY6Pp8hUSsGqpMCV2uza/lhq4C4RoWg=="
]
}
{
"sub": "de.bmi.eudi-wallet.wallet-provider-backend",
"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "32jtyqhBGxKxqeihaRsmW449oB9hcMUSgNCxDjHfADo",
"y": "3ARvwMghvfz7zAcGEdwQj2h5DQU64BezdaSthn7qJzk"
}
},
"iat": 1750742508,
"exp": 1750828908,
"status" : {
"status_list" : {
"uri" : "https://wallet-provider-backend.eudi-wallet.de/status/0953e816-c84e-4ae4-a955-d2190552f21b",
"idx" : 5217
}
}
}
Signed by wb_wia_auth_prvk
Proof of Possession JWT for Wallet Instance Attestation (WIA)¶
The wi_wia_pop is a proof of possession signed by the Wallet Instance, attesting to the possession and usage of the WIA towards the Wallet Provider Backend. The format is aligned with Section 5.2 of attestation-based client authentication, but contains slight differences.
In accordance to the rules defined in the draft, the wi_wia_pop contains:
- JOSE Header
typas recommended by JWT BCP - JOSE Header
algindicating ECDSA NIST P-256 - JOSE Header
jwkcontaining the serialized wi_wia_pubk - JWT Claim
audreferencing the URL of the Wallet Provider Backend - JWT Claim
jticontaining a UUID - JWT Claim
iat: current time, indicating the issuance date of the PoP - JWT Claim
wb_auth_challengecontaining the serialized wb_auth_challenge
Note: The Wallet Backend is using the challenge for replay protection instead of jti, but the draft of attestation-based client authentication requires jti to be present in any case.
Below is a non-normative example of a wi_wia_pop:
Protected headers:
{
"typ": "oauth-client-attestation-pop+jwt",
"alg": "ES256",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "32jtyqhBGxKxqeihaRsmW449oB9hcMUSgNCxDjHfADo",
"y": "3ARvwMghvfz7zAcGEdwQj2h5DQU64BezdaSthn7qJzk"
}
}
{
"aud": "https://wallet-provider-backend.eudi-wallet.de",
"jti": "d25d00ab-552b-46fc-ae19-98f440f25064",
"iat": 1750742508,
"wb_auth_challenge": "eyJ0eXAiOiJ3Yi1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJub25jZSI6IjhjM2YyODM4LTU1Y2QtNGE0MC1iOTg5LWEzMzYyNDhkOGNlOCIsImlhdCI6MTc1MDc0MjUwOH0.VD0P5y2EZbut0_JxCd_nwo0RNDZhndzO7M2xWzZ7xyA"
}
Signed by wi_wia_pop_prvk