<!-- PDF-show
\newpage
-->

# PID Option C: Signed Credential with Secure Element

## Basic Idea

In this flow, long-lived, digitally signed PID credentials in ISO mdoc and IETF
SD-JWT VC formats are issued to the Wallet Instance utilizing the OpenID4VCI
protocol. During the issuance, the user is authenticated using the eID card, so
when these PID credentials are presented to the Relying Parties over OpenID4VP
protocol, there is no need for the user to use physical eID card. This flow
trusts Wallet Instance to manage the keys on the device without Wallet Backend's
involvement (unlike Option C').

To improve user experience and prevent the users from having to tap an eID card
every time a batch of Credentials needs to be refreshed and tapping an eID card
as many times as there are Credentials in a batch, a concept of Seed Credential
is introduced. A Seed Credential is used to acquire a set of single-use Batch
Credentials from the Provider. The Wallet can then present these Batch
Credentials to the Relying Parties. The user only needs to present the physical
ID card once - to acquire the Seed Credential - instead of every presentation.

Such Seed Credential is issued by a PID Provider to the Wallet as a signed
DPoP-bound refresh token and can be stored for a longer period. The refresh
token is bound to the key stored on the wallet device itself.

Wallet Attestation PoP and DPoP Proof are bound to the keys managed by the
wallet device.

Because the PID is long lived, the
[revocation](../functions/00-pid-issuance-and-presentation/index.md#revocation)
implementation is crucial.

## Credential formats

Two solutions are described:

- **ISO mdoc** The ISO mdoc credential format is used with
    - issuerAuth as issuer data authentication, a COSE_Sign1 signature over the
    MobileSecurityObject (see ISO 23220-4 7.1.3.4.2.1); containing
        - the Wallets long-lived key in `deviceKeyInfo`
        - signed hashes in the `valueDigests`
    - deviceSignature as mdoc authentication method, a COSE_Sign1 MAC over the
    deviceAuthentication data (see ISO 18013-5 9.1.3.5)
        - containing the PID data
- **SD-JWT VC** The SD-JWT VC credential format is used with
    - SD-JWT signed with JWS by the PID Provider; containing
        - the Wallets long-lived key in `cnf`
        - the signed hashes in `_sd` arrays
    - the Disclosures containing the PID data

## Cryptographic Formats

### Issuance

Long-Term keys:

- PID Provider has long-term key pair $(pp\_pub, pp\_priv)$ which is used
    - to sign over the issued Credential
    - to sign over the Refresh Token JWT
- RP has long-term key pair $(rp\_pub, rp\_priv)$ which is used
    - to sign over the authorization request, authenticating its contents
- Wallet app has device key pair $(device\_pub, device\_priv)$ which is used
    - to generate proof of possession of a Credential
- Wallet app has device key pair $(device\_dpop\_pub, device\_dpop\_priv)$ which
  is used
    - to generate proof of possession of a Refresh Token

## Artifacts

### Issuance of a Credential

- PID Provider issues SD-JWT (plus Disclosures): $sd\_jwt :=
  \text{sign}(\mathit{hashed\_eID\_data}, device\_pub)_{pp\_priv}$

### Issuance of the Refresh Token

- PID Provider issues a refresh token: $refresh\_token :=
  \text{sign}((eID\_data)_{pp\_data}, expiration)_{pp\_priv}$. The refresh token
  itself is bound to $device\_dpop\_priv$ via DPoP token binding mechanisms.
  **Note that the content of the refresh token needs to be protected against
  modification.**

### Presentation

- $kb\_jwt := \text{sign}(nonce, audience, \text{hash}(sd\_jwt,
  disclosures))_{device\_priv}$

<!-- PDF-show
\newpage
-->

### Dependencies

*TODO: May want to expand to include metadata.*

```plantuml
digraph G {

  subgraph cluster_pid_provider {
    style=filled
    color=lightblue
    label="PID Provider"
    pp [label="🗝 (pp_priv, pp_pub)"]
    user_data [label="eID data"]
  }

  subgraph cluster_wallet {
    style=filled
    color=lightgreen
    label="Wallet"
    nonce_audience [label="nonce, audience"]
    dpop [label="DPoP proof (dpop_nonce)"]
    dev [label="🗝 (device_pub, device_priv)"]
    dpop_key [label="🗝 (dpop_priv, dpop_pub)"]
  }
  pp -> dev [label="sign (SD-JWT)"]
  pp -> user_data [label="sign (SD-JWT)"]

  dev -> nonce_audience [label="sign (KB-JWT)"]
  dpop_key -> dpop [label="sign"]
}
```

Note: Wallet attestation not shown in this chart.

<!-- PDF-show
\newpage
-->

## Sequence Diagrams and Step-by-Step Description of Each Step

Each step of the protocol will be explained using a sequence diagram followed by
a step-by-step description.

### Wallet Activation

To initialize the wallet, the Wallet obtains wallet attestation as defined in
[Wallet Attestation](Wallet-Attestation.md).

### Issuance

#### [Sequence Diagram] Issuance

[User Journey: PID Issuance - Issuer
Signed](../user_journeys/PID-IssuerSigned-issuance.png)

```plantuml
@startuml

'Ensure messages are not too wide
skinparam maxMessageSize 200
skinparam wrapWidth 500

'Macro for colored [TLS] block
!function tls()
!return "<color #118888>[TLS]</color>"
!endfunction

'Align text on arrows to center
skinparam sequenceMessageAlign center

'padding between boxes
skinparam BoxPadding 100

autonumber "<b>(000)"

title PID Issuance over OpenID4VCI using Issuer-Signed Credentials (generic)

actor u as "User\nOpenID Holder"
participant wscd [
                  Wallet Secure Cryptographic Device
                  (WSCD)
                  ----
                  Long-term Key: (//device_pub//, //device_priv//)
                 ]
participant w as "User's EUDI Wallet Instance\n(eID-Client)"
participant i [
               PID Provider
               (eService+eID Server)
               ----
               Long-term Key: (//pp_pub//, //pp_priv//)
              ]

u --> w : open wallet, unlock wallet
hnote over w #dfd: Screen: launch_wallet
hnote over w #dfd: Screen: unlock_wallet
u --> w : request issuance of PID
hnote over w #dfd: Screen: credential_catalog

note over w,i: PID Issuer and EUDI Wallet have inherent trust relationship, metadata may be pre-configured or retrieved

w -> i : tls() HTTP POST </session_endpoint> wallet attestation nonce
i -> i : generate and store nonce
i --> w : tls() HTTP 200 <wallet attestation nonce>

w <-> wscd : get proof of possession for wallet attestation (wallet attestation nonce)

note right : Attestation guarantees with high certainty that Wallet is trustworthy and not manipulated

w -> i : tls() HTTP POST PAR (client_id, code_challenge, wallet attestation+PoP, either scope or authorization_details)
i -> i : verify wallet attestation and check Wallet Provider solution status on trust list
i --> w : tls() HTTP 200 request_uri

w -> i : tls() HTTP GET <OpenID4VCI Authorization Request(request_uri)>

hnote over w #dfd: Screen: consent_add_credential
hnote over w #dfd: Screen: eid_start

group Read eID or Smart eID acc. to BSI TR-03130
i --> w : tls() HTTP 200 starting the eID Process
w <-> i : eID Process
u <--> w : <eID-PIN>
hnote over w #dfd: Screen: eid_pin

'newpage

w <-> i : eID Process
w -> i : tls() HTTP GET finishing the eID process with refreshUrl
hnote over w #dfd: Screen: eid_nfc_data
end

i --> w : tls() HTTP 302 <OpenID4VCI Authorization Response(authorization code)>

group Generate initial DPoP nonce
w -> w : generate placeholder DPoP proof with generic (not WSCD-bound) key pair

w -> i : tls() HTTP POST <Token Request(DPoP Header with placeholder proof, authorization code, PKCE code_verifier)>
i -> i: generate and store dpop_nonce
i -> w : tls() HTTP 400 <Bad Request (DPoP nonce Header with dpop_nonce, error: "use_dpop_nonce")>

note left : The Wallet should check at this point, whether the Token Endpoint delivered the expected error and nonce. If not, this needs to be handled (retry or abort gracefully).
w -> w: store dpop_nonce
end

'generate DPoP proof with DPoP key
group WSCD
w <-> wscd: generate DPoP key pair (//dpop_pub//, //dpop_priv//)

w -> w: prepare DPoP proof for WSCD bound DPoP key incl. dpop_nonce and iat

w -> w: hash(DPoP proof for WSCD bound key)

w -> wscd: sign hash of DPoP proof

wscd -> wscd: sign hash of DPoP proof with //dpop_priv//

wscd --> w: signed hash of DPoP proof

w -> w: assemble DPoP proof JWT for WSCD bound key with signature
end

w -> i : tls() HTTP POST <Token Request(authorization code, PKCE code_verifier, wallet attestation, DPoP Header)>
i -> i : lookup authorization code\ngenerate Token Response with DPoP-bound access token\nverify PKCE challenge
i --> w : tls() HTTP 200 <Token Response(DPoP-bound access_token, c_nonce, optional authorization_details)>

w <-> wscd : generate device binding key pair (//device_pub//, //device_priv//) and proof of possession with c_nonce
hnote over w #dfd: Screen: device_authenticator

w -> w : generate credential response encryption key pair (//cre_eph_pub//, //cre_eph_priv//)
w -> w : create credential_response_encryption object with jwk containing //cre_eph_pub//

w -> i : tls() HTTP POST <Credential Request(DPoP-bound access token, //device_pub//, credential_response_encryption object)>
i -> i : lookup access token and validate key proof

alt #ddf C: ISO mdoc
  i -> i : create mdoc with eID data and //device_pub//, signed by //pp_priv//, and matching NameSpaceBytes
  i -> i : generate encrypted credential response JWT using the values received in the credential_response_encryption object
  i -> i : generate and store dpop_nonce
  i -> w : tls() HTTP 200 <Credential Response (DPoP nonce Header with dpop_nonce, JWT(<color blue>mdoc</color>))>
else #dfd C: SD-JWT VC
  i -> i : create SD-JWT VC with eID data and //device_pub//, signed by //pp_priv//, and matching Disclosures
  i -> i : generate encrypted credential response JWT using the values received in the credential_response_encryption object
  i -> i : generate and store dpop_nonce
  i --> w : tls() HTTP 200 <Credential Response (DPoP nonce Header with dpop_nonce, JWT(<color blue>SD-JWT VC, Disclosures</color>))>
end

w -> w : decrypt credential response JWT
w -> w : store PID credential
note left #FFAAAA: PID is signed data
w -> w: store dpop_nonce
hnote over w #dfd: Screen: success
hnote over w #dfd: Screen: home
@enduml
```

<!-- PDF-show
\newpage
\blandscape
-->

#### [Step-by-Step Description] Issuance

1. The user opens and unlocks the Wallet.
2. The user browses through the pre-configured credential catalog and chooses to
   request a PID.
3. The Wallet requests a fresh nonce for the wallet attestation nonce (wallet
   attestation).
4. The PID Provider generates a fresh nonce linked to the issuance session.
5. The PID Provider returns the wallet attestation nonce to the Wallet.
6. The Wallet performs a wallet attestation.
   - Optionally it fetches a new wallet attestation from the Wallet Provider if
     none exists yet.
   - It generates a proof of possession (PoP) for the public key of the wallet
     attestation using its WSCD.
7. The Wallet sends the Pushed Authorization Request to the PID Provider
   containing
   - the Wallet Provider's client_id,
   - the authorization_details for PID,
   - a PKCE code_challenge,
   - a wallet attestation and proof of possession,
   - either scope or an authorization_details parameter requesting the PID.
8. The PID Provider verifies the wallet attestation and its proof of possession
   and validates the certification status of the Wallet Solution on a trust
   list.
9. The PID Provider returns a request_uri that is bound to the Pushed
   Authorization Request.
10. The Wallet sends the Authorization Request containing
    - the PAR request_uri.
11. The PID Provider responds with the first step to start the eID process with
    the wallet app, e.g. the tcToken. Note that this is the direct HTTP Response
    to Step 14.
12. Further communication is exchanged to perform the eID process.
13. The user provides the eID PIN to the wallet app.
14. Further communication is exchanged to perform the eID process.
15. The eID process is finished and as a final step the Wallet sends a request
    to the PID Provider calling the refreshURL. From now on Wallet and PID
    Provider are using the TLS-PSK channel generated by the eID flow.
16. The PID Provider responds to the Wallet with an Authorization Response
    containing
    - the auth code.
17. The Wallet generates (and stores) a placeholder DPoP proof JWT using a generic
    (not HSM-bound) keypair to trigger an error response from the Token endpoint
    necessary to retrieve the `dpop_nonce`.
18. The Wallet sends a Token Request to the PID Provider, containing the
    placeholder DPoP proof JWT.
19. The PID Provider generates and stores a `dpop_nonce`.
20. The PID Provider responds with the expected error "use_dpop_nonce",
    containing the `dpop_nonce` to be used from now on in the DPoP nonce header.
21. The Wallet extracts and stores the `dpop_nonce`.
22. The Wallet generates a new key pair for DPoP (*dpop_pub*, *dpop_priv*).
23. The Wallet now prepares the actual DPoP proof for the WSCD bound
    `dpop_pub` including the `dpop_nonce` and `iat`.
24. The Wallet hashes the DPoP proof.
25. The Wallet sends a request to the WSCD to sign the hash of the
    DPoP proof for the WSCD bound key.
26. The WSCD signs the hash of the DPoP proof for the WSCD bound key with
    *dpop_priv*.
27. The WSCD returns the signed hash of the DPoP proof for the WSCD bound key
    to the Wallet.
28. The Wallet assembles the DPoP proof JWT for the WSCD bound key using the
    signature received in the previous step.
29. The Wallet sends a Token Request to the PID Provider containing
    - the auth_code from Authorization Response,
    - the PKCE code_verifier matching the code_challenge from Authorization
      Request,
    - the wallet attestation and proof of possession,
    - a DPoP JWT.
30. The PID Provider matches the code, verifies the PKCE code_verifier to the
    previously received code_challenge and verifies the wallet attestation. It
    then generates an access token bound to the DPoP key.
31. The PID Provider sends a Token Response containing
    - DPoP-bound access token and
    - a c_nonce,
    - an authorization_details object, in case the authorization_details
      parameter was used in the Authorization Request.
32. The Wallet generates a new key pair for device binding (*device_pub*,
    *device_priv*) and signs the c_nonce using its WSCD.
33. The Wallet generates a new ephemeral keypair (*cre_eph_pub*,
    *cre_eph_priv*).
34. The Wallet creates the `credential_response_encryption` JSON object
    containing the following information:
    - a jwk containing the *cre_eph_pub*
    - the JWE alg parameter
    - the JWE enc parameter
35. The Wallet sends a Credential Request to the PID Provider containing
    - the DpoP-bound access token,
    - the device binding key *device_pub* and the proof of possession and
    - the `credential_response_encryption` object.
36. The Issuer validates the access token and the proof of possession.
37. **(mdoc)** The PID Provider creates the mdoc by signing with *pp_priv*
    containing
    - the issuerAuth with the *device_pub* as deviceKey and hashes of the eID
      data,
    - the eID data as NameSpaceBytes and
    - the status management information
38. **(mdoc)** The PID Provider creates an encrypted JWT (JWE) using the values
    received in the `credential_response_encryption` object and adds (among
    others) the PID as mdoc to the payload.
39. **(mdoc)** The PID Provider generates and stores a fresh `dpop_nonce`.
40. **(mdoc)** The PID Provider sends the Credential Response JWT containing
    - the PID as mdoc and
41. **(SD-JWT)** The PID Provider creates SD-JWT VC by signing with *pp_priv*
    containing
    - the SD-JWT with the *device_pub* as confirmation claim and hashes of the
      eID data,
    - the eID data as Disclosures and
    - the status management information
42. **(SD-JWT)** The PID Provider creates an encrypted JWT (JWE) using the
    values received in the `credential_response_encryption` object and adds
    (among others) the PID as SD-JWT VC to the payload.
43. **(SD-JWT)** The PID Provider generates and stores a fresh `dpop_nonce`.
44. **(SD-JWT)** The PID Provider sends the Credential Response JWT containing
    - the PID as SD-JWT VC.
45. The Wallet decrypts the Credential Response JWT using the *cre_eph_priv* and
    retrieves the PID.
46. The Wallet stores the PID credential.
47. The wallet stores the `dpop_nonce`.

### Presentation

#### [Sequence Diagram] Presentation

[User Journey: PID Presentation - Issuer
Signed](../user_journeys/PID-IssuerSigned-presentation.png)

```plantuml

@startuml
'Ensure messages are not too wide
skinparam maxMessageSize 200
skinparam wrapWidth 300


'Macro for colored [TLS] block
!function tls()
!return "<color #118888>[TLS]</color>"
!endfunction

'Align text on arrows to center
skinparam sequenceMessageAlign center

'padding between boxes
skinparam BoxPadding 100

autonumber "<b>(000)"

title PID presentation over OpenID4VP

actor u as "User\nOpenID Holder"
participant b as "Browser App\n(same device)"
participant v [
                Relying Party
                ----
                ""Long-term Key: (//rp_pub//, //rp_priv//)""
]
participant w [
                User's EUDI Wallet Instance
                (eID-Client)
                ----
                ""Device binding Key: (//device_pub//, //device_priv//)""
]
participant wscd as "Wallet Secure Cryptographic Device\n(WSCD)"

u --> b : browse to application
hnote over b #dfd: Screen: same_device_relying_party_start
b -> v : tls() HTTP GET <rp-website>

v -> v : generate ephemeral key pair (//rp_eph_pub//, //rp_eph_priv//)

v -> v : create OpenID4VP Authorization Request,\n sign with //rp_priv//,\n store under <request_uri>
note left: Authorization Request includes:\n- presentation_definition\n- purpose\n- state\n- nonce\n- //rp_eph_pub// \n- response_uri

v -> v : generate new browser session <color:#909>session_id</color> and bind the authorization request to it

v --> b : tls() HTTP 200 HTML containing wallet-link openid4vp://authorize?")\nclient_id=..&request_uri=<request_uri>\nSet-Cookie: sid=<color:#909>session_id</color>
u --> b : action to start flow/launch wallet
b -> w : launch with wallet-link openid4vp://
note right #fc7: Potential security risk: Wallet app may be spoofed by malicious app
hnote over w #dfd: Screen: launch_wallet

'newpage

u --> w : unlock wallet
note right: may be moved to later point in flow or removed, see notes.
hnote over w #dfd: Screen: unlock_wallet

w -> v : tls() HTTP GET <request_uri>
note right #fc7: Potential privacy risk: RP learns existance of wallet app and potentially identifying information (e.g., headers)
v --> w : tls() HTTP 200 <JWT-Secured Authorization Request>

w -> w : validate Authorization Request JWT using //rp_pub//

u <--> w : user consent to present PID to Relying Party for given purpose
hnote over w #dfd: Screen: consent_present_credential
hnote over w #dfd: Screen: device_authenticator

alt #ddf B.1.1: ISO mdoc
  w -> w : prepare mdoc presentation according to <presentation_definition> by removing unnecessary NameSpaceBytes
  w -> w : calculate SessionTranscript (mDocGeneratedNonce, clientId, responseUri, nonce) and generate deviceAuth payload

else #dfd B.1.2: SD-JWT VC
  w <-> w : prepare SD-JWT presentation according to <presentation_definition> by removing unnecessary Disclosures
  w <-> w : generate KB-JWT payload (nonce, audience and hash of SD-JWT and disclosures)
end

w <-> wscd : sign payload with //device_priv//

'newpage

alt #ddf C: ISO mdoc
  w -> w : assemble deviceAuth and build presentation with issuerSigned and deviceSigned(deviceAuth)
else #dfd C: SD-JWT VC
  w -> w : assemble KB-JWT and build presentation with SD-JWT, selected Disclosures and KB-JWT
end
w -> w : create vp_token and presentation_submission
w -> w : add optionally other presentations according to the presentation_definition

w -> v : tls() HTTP POST encrypted <Authorization Response(presentation_submission, vp_token, state)>

v -> v : look up state in existing sessions\ncreate & store response_code for session

v --> w : tls() HTTP 200 <redirect_uri incl. response_code>

w -> b : launch browser with <redirect_uri with response_code>
hnote over w #dfd: Screen: success_redirect

b -> v : tls() HTTP GET <redirect_uri with response_code>\nCookie: sid=<color:#909>session_id</color>

v -> v : look up session with <color:#909>session_id</color> and match response_code

'newpage

alt #ddf B.1.1: ISO mdoc
  v -> v : verify contents of <vp_token>:\n- verify mdoc issuerAuth PID\n- verify deviceAuth with //device_priv// from issuerAuth\n- calculate and validate correct SessionTranscript
else #dfd B.1.2: SD-JWT VC
  v -> v : verify contents of <vp_token>:\n- verify SD-JWT PID\n- verify KB-JWT with //device_priv// from SD-JWT\n- validate nonce and audience from KB-JWT
end

v --> b : tls() HTTP 200 <HTML with continued UX flow>
hnote over b #dfd: Screen: same_device_relying_party_identified

@enduml
```

<!-- PDF-show
\elandscape
-->

#### [Step-by-Step Description] Presentation

Note: While certain assumptions about session management of the Relaying Party
are made here, the concrete implementation is considered out of scope for this
document. The usual security considerations for web session management apply.

1. The user browses to Relying Party (RP) website
2. Browser app on the user's device opens the RP website
3. RP generates a key pair to be used for ECDH key agreement for SD-JWT HMAC'ing
4. RP generates an OpenID4VP Authorization Request and stores it under a
   `request_uri` (e.g., `https://rp.example.com/oidc/request/1234`);
   - The request is bound to the user's browser session
   - It is signed using a key bound to the RP's metadata that can be retrieved
     using the RP's client_id
   - It contains the ephemeral key for response encryption
   - It contains RP's nonce and state
   - It contains the RP's response_uri endpoint for sending the Authorization
     Response over POST
5. RP generates a new browser session and binds the generated Authorization
   Request to it
6. RP returns a HTML page to the browser containing a link to the wallet app
   (e.g.,
   `openid4vp://authorize?client_id=..&request_uri=https://rp.example.com/oidc/request/1234`);
   a cookie with the browser session id is set
7. The user clicks on the link
8. The RP website navigates to the custom scheme link to launch the wallet app
9. The user unlocks the wallet app (see notes below)
10. The wallet app retrieves the Authorization Request from the RP website
    (e.g., `https://rp.example.com/oidc/request/1234`)
11. The wallet app receives the Authorization Request
12. The wallet app validates the Authorization Request using the RP's public key
    - Was the signature valid and the key bound to the RP's metadata?
    - **Security:** This ensures that the Authorization Request was not tampered
      with; it does not ensure that the party that sent the Authorization
      Request is the RP.
13. The Wallet displays information about the identity of the Relying Party and
    the purpose, the user gives consent to present the PID.
14. **(mdoc)** The Wallet prepares an mdoc presentation according to the
    presentation_definition by removing NameSpaceBytes of not disclosed
    attributes.
15. **(mdoc)** The Wallet calculates the SessionTranscript according to
    ISO-18013-7 Annex B.4.4 from mDocGeneratedNonce, client_id, responseUri,
    nonce and generates the deviceAuthentication structure from
    SessionTranscript and NameSpaceBytes for signing.
16. **(SD-JWT)** The Wallet generates an SD-JWT VC presentation according to the
    presentation_definition by removing Disclosures of not disclosed attributes.
17. **(SD-JWT)** The Wallet creates the header and payload for the KB-JWT from
    audience, nonce, hash of issuer-signed JWT+Disclosures for signing.
18. The Wallet signs the payload with *device_priv*.
19. **(mdoc)** The Wallet assembles the deviceAuth from header, payload and
    signature and builds the presentation from deviceAuth and issuerSigned
20. **(SD-JWT)** The Wallet assembles the KB-JWT from header, payload and
    signature and builds the SD-JWT VC presentation from issuer-signed JWT,
    Disclosures and KB-JWT
21. The wallet app creates a VP token and a presentation submission from the
    received SD-JWT PID.
22. Optional: The wallet app can add further presentations
23. The wallet app sends the VP token and presentation submission to the RP
    (encrypted to the RP's public key *rp_eph_pub*).
24. The RP finds a session with the state and generates a response_code for this
    session
25. The RP returns the redirect_uri with the response_code to the wallet app
26. The wallet app launches the browser with the redirect_uri and response_code.
27. The browser sends the redirect_uri and response code to the RP, attaching
    the browser session id as a cookie.
28. The RP looks up whether there exists a session with the session id from the
    cookie and a matching response_code
29. **(mdoc)** The RP verifies the PID in the VP token and verifies the
    SessionTranscript calculated from nonce, mDocGeneratedNonce, clientID,
    response_uri.
30. **(SD-JWT)** The RP verifies the SD-JWT PID in the VP token, verifies the
    KB-JWT using the *device_priv* in the SD-JWT, and verifies the nonce and
    audience in the KB-JWT
31. The RP considers the user to be identified in the session context and
    continues the UX flow.

## Extensions to the Protocols

This section defines extensions to the protocols required to implement this flow
(Option C).

### Issuer Session Endpoint (at the PID Provider)

Note that this extension is the same across multiple flows.

This endpoint is used by the Wallet to obtain `session_id` from the PID Provider
that is used to bind PoPs to the session and prove their freshness. Support for
this endpoint is REQUIRED.

To fetch the `session_id`, the Wallet MUST send an HTTP request using the POST
method and the `application/json` media type. The PID Provider MUST return the
HTTP Status Code 200 and a `session_id` parameter defined below.

- `session_id`: REQUIRED. String that is a unique session identifier, chosen as
  a cryptographically random nonce with at least 128 bits of entropy.

Communication with the Session Endpoint MUST utilize TLS.

Below is a non-normative example of a request to a Session Endpoint:

```http
POST /session_endpoint HTTP/1.1
Host: server.example.com
Content-Type: application/json

```

Below is a non-normative example of a response from a Session Endpoint:

```http
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "session_id": "iOiJSUzI1NiIsInR"
}
```

### OpenID4VCI Credential Issuer Metadata

Note that this extension is the same across multiple flows.

This document defines the following additional Credential Issuer Metadata
parameters:

- `session_endpoint`: REQUIRED. URL of the Credential Issuer's Session Endpoint,
  as defined in a previous section. This URL MUST use the `https` scheme and MAY
  contain port, path, and query parameter components.

## Usability Considerations

### Issuance

- Credential catalogue should inform users in advance of what is required for
  the successful issuance of the PID and what steps follow
- For reasons of transparency and to increase trust, PID Provider should provide
  sufficient information (metadata) for the consent screen. This allows users to
  learn everything relevant e.g. about the PID Provider itself, privacy and data
  retention
- eID process is integrated in Wallet. No context switch to the AusweisApp is
  required
- Physical ID card is required for issuing the PID credential
- Online-Ausweisfunktion must be activated
- eID PIN must be set by the user (replacement of the Transport PIN) and be
  known to them so that they can successfully confirm the process
- User must confirm the process with the eID PIN and the device authenticator
- User can have a PID credential derived from the eID on several end devices at
  the same time

### Presentation

- Offline support for PID representation
- Relying Party should inform users in advance of what is required for the
  process to be completed successfully and what steps follow
- It needs to be clarified whether the wallet app needs to be unlocked in this
  flow, as the device authenticator is requested again directly after the
  consent screen. This might create friction and feel redundant to users
- For reasons of transparency and to increase trust, Relying Parties should
  provide sufficient information (metadata) for the consent screen. This allows
  users to learn everything relevant e.g. about the relying party itself,
  privacy and data retention
- The user's data values for the requested attributes can be displayed on the
  consent screen
- The user only needs to confirm the PID presentation with the Device
  Authenticator
- Physical ID card is not required for PID presentation
- It must be ensured that users return to the correct tab in the correct browser
  in order to continue the process or know how to get there manually if
  necessary (especially for iOS devices, if the process was not started in the
  default browser)

## Privacy Considerations

- Unobservability:
    - Issuer: the issuer-signed credentials are under sole control of the
    Wallet, the usage of credentials is not recognized by the Issuer, even when
    revocation is used
    - Wallet Provider: see specific sub-options
- Unlinkability:
    - Outsider: Both OpenID4VCI and OpenID4VP are entirely encrypted using TLS,
    an outsider is therefore *not* able to link any transactions apart from the
    low-level network traffic itself
    - Relying Party: the same Relying Party will *not* be able to link
    transactions when batch-issued single use credentials are issued
    - Issuer: the PID Issuer will be able to link the transactions
    - Colluding Relying Parties: colluding Relying Parties will *not* be able to
    link transactions when batch-issued single use credentials are issued
    - Colluding Issuers: colluding issuers will *not* be able to link
    transactions when ephemeral or issuer-specific wallet attestations are used
    - Colluding Relying Party and Issuer: colluding PID Provider and Relying
    Party will be able to link transactions due to the nature of SD-JWT VC and
    ISO mdoc cryptography
- Repudiation:
    - Repudiation of Data Authenticity: issuer-signed credentials are not
    repudiable due to the nature of signature algorithms. This may be mitigated
    by key publication, but is currently out of scope
    - Repudiation of User binding: in the current design presentations are not
    repudiable due to the use of signature algorithms for key binding. ISO mdoc
    has the option to use deviceMac, which is currently not in scope.
- Selective Disclosure: both SD-JWT VC and ISO mdoc achieve selective disclosure
  by ensuring that the Wallet contains only those attributes (claims) that are
  requested by the Relying Party

<!-- PDF-show
\newpage
-->

## Security Considerations

- Level of Assurance:
- Unforgeability of Credentials: unforgeability is guaranteed by the signature
  of the issuer-signed credential, i.e. the SD-JWT or the issuerSigned
- Freshness of Presentations: freshness is guaranteed by the nonce provided by
  the Relying Party, which is integrated in the KB-JWT or deviceAuth, see
  [replay
  prevention](https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-preventing-replay-of-the-vp).
- User Binding of presentations: see specific sub-options
- Session Integrity:
    - Issuance: PID Provider and Wallet share a pre-configured trust
    relationship, established through certificate pinning and other mechanisms
    - Presentation: Session Integrity is supported by OpenID4VP through browser
    redirect, see [session
    fixation](https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-session-fixation).
- further topics:
    - In Presentation Step 008, a malicious app may spoof the wallet app; an
      attacker may
        - **on the attacker's own device:** Capture the request and replay it to
        a victim on another device, thus having the victim identify itself in a
        context of the attacker (**Relaying Attack breaking Identification
        Context**); or
        - **on the victim's device:** Capture the request and spoof the whole
        identification process or parts of it (**Wallet App Spoofing**).
    - In Presentation Step 008: An attacker acting as an RP can forward a
      request from a different RP.
        - As long as the request remains unchanged, we're in the **Relaying
        Attack breaking Identification Context**
        - If the attacker changes anything in the request, this will break the
        signature. The attacker could otherwise attempt to
            - insert the attacker's own ephemeral key, leading to an SD-JWT
          artifact that could be used in a different flow between the attacker
          and some other RP.
            - modify state or nonce or other data. **Q:** Any useful attacks
          resulting from this?
    - In Presentation Step 024: The RP must not consider the user identified at
      this point; it is important to have the browser redirect in the later
      steps.

## Open Topics

- integrate revocation mechanisms
- Security of PID Provider Interface in Issuance Step 3ff:
    - Are additional steps required to protect the interface to the PID
      Provider?
    - What exactly is the transaction binding?
    - How is the eID process tied to the process at the PID provider?