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

# PID Option C': Signed Credential with Cloud Support

## 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 using Wallet Backend to manage keys on behalf of the Wallet Instance,
under the assumption that keys managed on the mobile device cannot be secured in
a way that is appropriate for Level of Assurance High (unlike Option C).

To improve user experience and prevent the users from tapping 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 key from the
wallet backend, that the refresh token is bound to, is stored and managed by an
HSM in the wallet backend (WSCD) instead of the wallet device itself.

To authenticate the wallet instance, the user must set up a new Wallet PIN,
which is verified by the Wallet Backend.

Wallet Attestation PoP and DPoP Proof are bound to the keys managed by a wallet
backend, but since they contain session specific information (audience and a
nonce/session id) that should be known only to the wallet instance from a
privacy perspective, to generate a signature, the wallet instance sends only a
ready-to-be-signed hash to the wallet backend. Wallet Attestation PoP and DPoP
Proof require key attestation for the keys that they are bound to.

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

ToDo: explain the concept of a PIN

## Cryptographic Keys

Where applicable, each key name start with the entity that manages that key:

- `wb_` stands for Wallet Backend
- `pp_` stands for PID Provider
- `rp_` stands for Relying Party
- `device_` means Wallet Instance

Long-Term keys:

- Wallet Instance generates locally managed key pair $(device\_pub,
  device\_priv)$ which is used
    - to bind the PIN proof to the device
- Wallet Instance generates AES key $(pin\_salt)$ which is used
    - to derive the `pin_derived_eph_priv` used as PoP of Wallet PIN
- Wallet Backend has key pairs represented as $(wb\_attestation\_pub_wa,
  wb\_attestation\_priv_wa)$, $(wb\_attestation\_pub_kbp,
  wb\_attestation\_priv_kbp)$, $(wb\_attestation\_pub_ks,
  wb\_attestation\_priv_ks)$, and $(wb\_attestation\_pub_kd,
  wb\_attestation\_priv_kd)$ which are each used
    - to sign wallet instance's wallet attestations, used with the postfix `_wa`
    - to sign key attestation for the key that a PID is bound to, used with the
      postfix `_kbp`
    - to sign key attestation for the key that a seed credential is bound to,
      used with the postfix `_ks`
    - to sign key attestation for the key that a DPoP Proof is bound to, used
      with the postfix `_kd`
- Wallet Backend generates a key pair $(wb\_device\_pub, wb\_device\_priv)$
  which is used
    - to sign proof of possession of wallet attestation
- Wallet Backend generates HSM bound key pair $(wb\_dpop\_pub, wb\_dpop\_priv)$
  which is used
    - to generate DPoP proof (a key to which refresh token used as a seed
      credential is bound to)
- PID Provider has HSM bound long-term key pair $(pp\_pub, pp\_priv)$
    - to sign over the issued Credential
    - to sign over the Refresh Token JWT
- PID Provider has symmetric long-term key $(pp\_data)$ which is used
    - to encrypt eID data inside the refresh token
- Relying Party has long-term key pair $(rp\_pub, rp\_priv)$ which is used
    - to sign over the authorization request, authenticating its contents

ToDo: need to add an HSM bound key that wallet backend uses to hash the PoP
(associated with UUID & Issuer_ID)?

Transaction-specific keys:

- Wallet Backend generates cryptographic seed `c_seed` for batch key derivation
- Wallet Backend generates X batch key pairs $(batch\_kb\_X\_pub,
  batch\_kb\_X\_priv)$ from `c_seed` and keyIDx (`X` in the key name stands for
  the key's index) which is used
    - to sign credential presentation (KB-JWT/devAuth)
    - to sign proof sent in Credential Request during issuance
- Wallet Instance generates ephemeral key derived from user PIN
  $(pin\_derived\_eph\_pub, pin\_derived\_eph\_priv)$ which is used
    - to generate PIN proof of possession

Wallet attestation PoP is bound to a PID Issuer-generated session id to prove
its freshness.

Two PoPs each used to bind the PIN proof to the device and to prove possession
of a PIN are bound to a Wallet Backend-generated session id to prove their
freshness.

Note: The key derived from user PIN is not stored by the Wallet Instance,
instead it is generated every time the user enters the PIN.

## Artifacts

### Issuance of Issuer specific Wallet Attestations

- Wallet Backend creates wallet app attestation: $wallet\_app\_attestation :=
  \text{attestation}(wb\_device\_pub)_\text{wb\_attestation\_priv}$

### Issuance of the Refresh Token

- PID Provider issues a refresh token containing the encrypted eID data in a
  JWT: $refresh\_token := \text{sign}(\text{Enc}(eID\_data)_{pp\_data},
  expiration)_{pp\_priv}$. The refresh token itself is bound to $wb\_dpop\_priv$
  via DPoP token binding mechanisms. **Note that this is not the only way to
  protect the refresh token.**

### Issuance PID Batch Credential

- Wallet Backend generates $CloudWalletBatchKey := \text{sign}(\text{X tuples
  of} (keyIDx, batch\_kb\_X\_pub))_{wb\_attestation\_priv}$ and sends it to
  Wallet Instance
- PID Provider issues X
    - $sd\_jwt (and Disclosures) := \text{sign}(hashed\_eID\_data,
      batch\_kb\_X\_pub)_{pp\_priv}$ OR
    - $mdoc := \text{sign}(hashed\_eID\_data, batch\_kb\_X\_pub)_{pp\_priv}$
- Wallet app stores $(CloudWalletBatchKey, Credential)$ tuples with issuer_ID

### Presentation

- Wallet Backend creates $kb\_jwt := \text{sign}(nonce,
  audience)_{batch\_kb\_X\_priv}$ OR
- $device\_Auth$ for mdoc

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

### Dependencies

*TODO: May want to expand to include metadata.* *TODO: Beautify dependencies
diagram* *NOTE: The connection `pin_pop2 -> wb_session_id [label="bound to"]`
was removed because it let the image generator crash*

```plantuml
digraph G {
  node [shape=box]
  subgraph cluster_pid_provider {
    style=filled
    color=lightblue
    label="PID Provider"

    pp_session_id [label="pid_issuer_session_id"]
    seed_cred [label="refresh token used as a seed credential"]
    batch_C [label="X batch credentials"]
    
    pp [label="🗝 (pp_priv, pp_pub)"]
    pp_data [label="🗝 pp_data"]
  }

  subgraph cluster_wallet_backend {
    style=filled
    color=lightpink
    label="Wallet Backend"

    wb_session_id [label="wallet_backend_session_id"]
    seed [label="cryptographic seed"]
    wallet_att_pop_key [label="🗝 (wb_device_priv, wb_device_pub)"]
    dpop_key [label="🗝 (wb_dpop_priv, wb_dpop_pub)"]
    wb_attestation [label="🗝 (wb_attestation_priv, wb_attestation_pub)"]
    batch_key [label="🗝 (batch_kb_X_priv, batch_kb_X_pub)"]
    
    dpop [label="DPoP proof (dpop_nonce)"]
    wallet_att [shape=record, label="{ Wallet Attestation }"]
    key_att_seed [shape=record, label="{ Seed Credential Key Attestation (DPoP key) }"]
    key_att_cred [shape=record, label="{ PID Key Attestation (batch keys) }"]

  }

  subgraph cluster_wallet {
    style=filled
    color=lightgreen
    label="Wallet"

    wallet_key [label="🗝 (device_priv, device_pub)"]
    pin_salt [label="🗝 PIN salt key"]
    pin_key [label="🗝 (pin_derived_eph_priv, pin_derived_eph_pub)"]
    
    wallet_att_POP [shape=record, label="{ wallet attestation PoP (pid_issuer_session_id, aud, exp) }"]
    cr_and_kb [shape=record, label="{ proof sent in a Credential Request (batch_kb_X_pub, aud, c_nonce) | KB-JWT/devAuth }"]
    pin_pop1 [shape=record, label="{ PoP of device bound key (`pin_derived_eph_pub`, wallet_backend_session_id) }"]
    pin_pop2 [shape=record, label="{ PoP of PIN derived key (`device_pub`, wallet_backend_session_id) }"]
  }

  pp -> seed_cred [label="sign"]
  pp_data -> seed_cred [label="encrypt eID data"]
  pp -> batch_C [label="sign"]
  seed_cred -> dpop_key [label="bound to"]
  batch_C -> batch_key [label="bound to"]

  wallet_att_POP -> pp_session_id [label="bound to"]
  wb_attestation -> wallet_att [label="sign"]
  wallet_att_pop_key -> wallet_att_POP [label="sign"]
  wallet_key -> pin_pop1 [label="sign"]
  pin_key -> pin_pop2 [label="sign"]

  wb_attestation -> key_att_cred [label="sign"]
  wb_attestation -> key_att_seed [label="sign"]
  
  key_att_cred -> batch_key [label="attest"]
  key_att_seed -> dpop_key [label="attest"]
  
  pin_pop1 -> wb_session_id [label="bound to"]  
  wallet_att -> wallet_att_pop_key [label="bound to"]

  dpop_key -> dpop [label="sign"]
  seed -> batch_key [label="derive X times"]
  batch_key -> cr_and_kb [label="sign"]

  pin_salt -> pin_key [label="derive (with PIN)"]
}

```

<!-- 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

#### [Sequence Diagram] Wallet Activation

[User Journey: Wallet Activation - Issuer Signed -
Cloud](../user_journeys/PID-IssuerSigned-cloud-initialization.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 Wallet Activation

participant u order 1 [
                Holder
            ]
participant w order 3 [
                User's EUDI Wallet Instance\
                (eID-Client)
                ----
                ""Device Key: (//device_pub//, //device_priv//)""
                ""Wallet Attestation bound to //wb_device_pub//""
                ""PIN Salt: //pin_salt//""
            ]
participant wb  order 2 [
                User's EUDI Wallet Backend
                ----
                ""Long-term Keys: (//wb_attestation_pub//, //wb_attestation_priv//)""
                ""Long-term Key: (//wb_device_pub//, //wb_device_priv//)""
            ]


u --> w : open wallet
hnote over w #dfd: Screen: launch_wallet
u --> w : request wallet initalization
hnote over w #dfd: Screen: initialization_start
hnote over w #dfd: Screen: initialization

w -> wb : tls() HTTP POST </session_endpoint> wallet_backend_session_id
wb -> wb : generate and store wallet_backend_session_id
wb -> w : tls() HTTP 200 <wallet_backend_session_id>

w -> w : perform and get wallet attestation from OS attestation service (wallet_backend_session_id)
note right : Platform (Android/iOS) specific mechanisms are used for  attestation. This guarantees with high certainty that the Wallet app and underlying OS is trustworthy and not manipulated


w -> w : generate and store AES key: //pin_salt//
u <--> w : set Wallet PIN
hnote over w #dfd: Screen: initialization_set_wallet_pin

'newpage

w -> w : generate key pair (//pin_derived_eph_pub//, //pin_derived_eph_priv//) from KDF(Wallet PIN, encrypt_AES(//pin_salt//, Wallet PIN))
note right: used as knowledge factor for authentication with wallet backend, keys are discarded after every use
w -> w : generate device bound key pair (//device_pub//, //device_priv//)
note right: used as possession factor for authentication with wallet backend


w -> w : generate PoP for pin derived ephemeral key - sign(wallet_backend_session_id | //device_pub//)<sub>//pin_derived_eph_priv//</sub>
w -> w : generate PoP for wallet app's key - sign(wallet_backend_session_id | //pin_derived_eph_pub//)<sub>//device_priv//</sub>
note right: proof of ownership must be built from both the device bound key and the key derived from the user PIN

w -> wb : tls() HTTP POST <//pin_derived_eph_pub//, //device_pub//, PoP for pin derived ephemeral key, PoP for wallet app's key, wallet attestation>

'newpage

wb -> wb : verify wallet attestation\ncheck device black list (Vulnerability Management)\nstore security relevant device attributes in session

wb -> wb: check signatures

wb -> wb: generate UUID as identifier for the wallet instance

wb -> wb: set up retry counter and store retry counter, //pin_derived_eph_pub//, //device_pub//, security relevant device attributes from session under UUID


wb -> w : tls() HTTP 200 <UUID, wallet_backend_session_id>
note left: session has to be short lived

w -> w : store UUID and wallet_backend_session_id
hnote over w #dfd: Screen: home

@enduml
```

#### [Step-by-Step Description] Wallet Activation

1. The User opens the Wallet.
2. The User requests wallet activation.
3. The Wallet requests fresh wallet_backend_session_id
4. The Wallet Backend generates and links it to the session
5. The Wallet Backend returns the wallet_backend_session_id to the Wallet
6. The Wallet performs a wallet attestation using the OS specific attestation
   services
    - this attestation provides a statement about the integrity and authenticity
      of the Wallet and the underlying software and hardware components of the
      smartphone
7. The Wallet generates an AES key (*pin_salt*)
    - This key will be used to generate a salt used by the Wallet PIN key
      derivation mechanism
8. The User enters the new Wallet PIN (most likely twice to ensure that the user
   has entered the intended PIN)
9. The Wallet proves possession of the Wallet PIN.
    - See "Wallet proving possession of the PIN" module for a detailed
      description of the steps.
10. part of an above module
11. part of an above module
12. part of an above module
13. The Wallet sends a request to the Wallet Backend; containing
    - *pin_derived_eph_pub* and PoP
    - *device_pub* and PoP
    - wallet attestation incl. wallet_backend_session_id
14. The Wallet Backend verifies the wallet attestation and stores security
    relevant details from the attestation in the current session.
    - In addition, the Wallet Backend checks whether the smartphone is on the
      device blacklist (from Vulnerability Management). If this is the case, no
      wallet attestation will be issued
15. The Wallet Backend validates the PoP for *pin_derived_eph_pub* and
    *device_pub*
16. The Wallet Backend generates a UUID as an identifier for the Wallet instance
17. The Wallet Backend initializes the retry counter for the wallet PIN and
    stores the retry counter, *pin_derived_eph_pub*, *device_pub*,
    security-relevant device attributes (from session) under the UUID of the
    Wallet instance
18. The Wallet Backend returns the UUID and a `wallet_backend_session_id` (to
    request a Wallet Attestation) to the Wallet
19. The Wallet stores the UUID and the `wallet_backend_session_id`

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

### Issuance of Issuer specific Wallet Attestations

#### [Sequence Diagram] Issuance of Issuer specific Wallet Attestations

```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 Issuance of Issuer specific Wallet Attestations

participant u order 1 [
                Holder
            ]
participant w  order 3 [
                User's EUDI Wallet Instance\
                (eID-Client)
                ----
                ""Device Key: (//device_pub//, //device_priv//)""
                ""Wallet Attestation bound to //wb_device_pub//""
                ""PIN Salt: //pin_salt//""
            ]
participant wb  order 2 [
                User's EUDI Wallet Backend
                ----
                ""Long-term Key: (//wb_device_pub//, //wb_device_priv//)""
            ]


alt #dfd Session from Wallet Activation still Valid
    w -> wb: tls() HTTP POST <getWalletAttestation(UUID, wallet_backend_session_id (from Wallet Activation))>
  else #fdf Session from Wallet Activation no longer Valid
    w -> wb: tls() HTTP POST <getWalletAttestation(UUID, wallet_backend_session_id (from Wallet Activation))>
    wb -> wb : generate and store wallet_backend_session_id
    wb -> w: tls() HTTP 400 <wallet_backend_session_id>
    u <--> w : input Wallet PIN
    hnote over w #dfd: Screen: wallet_pin
    w -> w : generate key pair (//pin_derived_eph_pub//, //pin_derived_eph_priv//) from KDF(Wallet PIN, encrypt_AES(//pin_salt//, Wallet PIN))

    w -> w : generate PoP for pin derived ephemeral key - sign(wallet_backend_session_id | //device_pub//)<sub>//pin_derived_eph_priv//</sub>
    w -> w : generate PoP for wallet app's key - sign(wallet_backend_session_id | //pin_derived_eph_pub//)<sub>//device_priv//</sub>

    w -> wb : tls() HTTP POST <UUID, PoP for pin derived ephemeral key, PoP for wallet app's key>

    wb -> wb: load instance information for UUID
    note left: Instance Information: retry counter, //pin_derived_eph_pub//, //device_pub//, security relevant device attributes
    wb -> wb: check user pin retry
    note right: request would be refused in case of locked pin
    wb -> wb: check security of device against Vulnerability Management information
    note left: PIN will not be validated if device is known to be insecure
    wb -> wb: check signatures
    note right: user pin retry counter would be increased in case of failed pin signature check, user pin would be locked after threshold is exeeded
end

'newpage

wb -> wb: generate HSM bound key pair (//wb_device_pub//, //wb_device_priv//) and associate with UUID and issuer_ID
note left: issuer_ID is a random value generated by the wallet backend

wb -> wb : Generate wallet attestation with //wb_device_pub// and sign with //wb_attestation_priv//
note left: wallet attestation as defined in "OpenID4VC High Assurance Interoperability Profile with SD-JWT VC - draft 00"

wb -> w : tls() HTTP 200 <walletAttestation, issuer_ID>

w -> w : store walletAttestation under issuer_ID

@enduml
```

#### [Step-by-Step Description] Issuance of Issuer specific Wallet Attestations

##### Case 1: wallet_backend_session_id from Wallet Activation still valid

1. The Wallet sends a GetWalletAttestation request to the Wallet Backend;
   containing
    - UUID
    - wallet_backend_session_id (from Wallet Activation)

##### Case 2: wallet_backend_session_id from Wallet Activation has expired

1. The Wallet sends a GetWalletAttestation request to the Wallet Backend;
   containing
    - UUID
    - wallet_backend_session_id (from Wallet Activation)
2. The Wallet Backend generates and stores a new wallet_backend_session_id
3. The Wallet Backend answers with a HTTP response code 440 (Login Time-out)
   containing a new wallet_backend_session_id (required for authentication)
4. The User enters the Wallet PIN
5. The Wallet proves possession of the Wallet PIN
    - See "Wallet proving possession of the PIN" module for a detailed
      description of the steps
6. part of an above module
7. part of an above module
8. The Wallet sends a request to the Wallet Backend; containing
    - UUID
    - PoP for `pin_derived_eph_priv`
    - PoP for `device_priv key`
9. The Wallet Backend checks Wallet Instance.
    - See [Wallet Backend checks the Wallet
      Instance](#wallet-backend-checks-the-wallet-instance) module for a
      detailed description of the steps.
10. part of an above module
11. part of an above module
12. The Wallet Backend validates the PoP for *pin_derived_eph_pub* and
    *device_pub*

##### Both cases conclude with these steps

1. The Wallet Backend generates a HSM bound key pair (*wb_device_pub/priv*) for
    Wallet Attestation and associates it with UUID and Issuer_ID
    - Issuer_ID is a unique random value that is used to identify which keys
      belong to which issuer, which is generated by the Wallet Backend
2. The Wallet Backend generates a Wallet Attestation including *wb_device_pub*
    and signs it with *wb_attestation_priv*
3. The Wallet Backend returns the Wallet Attestation and the corresponding
    Issuer_ID to the Wallet.
4. The Wallet stores the Wallet Attestation and corresponding Issuer_ID

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

### Issuance of a Refresh Token used as a Seed Credential

#### [Sequence Diagram] Issuance of a Refresh Token used as a Seed Credential

[User Journey: PID Issuance - Issuer Signed -
Cloud](../user_journeys/PID-IssuerSigned-cloud-issuance.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 Issuance of the Refresh Token over OpenID4VCI

participant u order 1[
                PID Holder
                ----
                ""PIN: (//user_pin//)""
            ]
participant w  order 3[
                User's EUDI Wallet Instance\
                (eID-Client)
                ----
                ""Device Key: (//device_pub//, //device_priv//)""
                ""Wallet Attestation bound to //wb_device_pub//""
                ""PIN Salt: //pin_salt//""
            ]
participant wb  order 2[
                User's EUDI Wallet Backend
                ----
                ""Long-term Key: (//wb_device_pub//, //wb_device_priv//)""
            ]
participant i  order 4[
                PID Provider
                (eService+eID Server)
                ----
                ""Long-term Key: (//pp_pub//, //pp_priv//)""
                ""eID data encryption Key: (//pp_data//)""
            ]


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> pid_issuer_session_id
i -> i : generate and store pid_issuer_session_id
i -> w : tls() HTTP 200 <pid_issuer_session_id>
hnote over w #dfd: Screen: consent_add_credential

group check pin

w -> wb: tls() HTTP POST </session_endpoint> wallet_backend_session_id
wb -> wb : generate and store wallet_backend_session_id
wb -> w : tls() HTTP 200 <wallet_backend_session_id>

u --> w: enter Wallet PIN
hnote over w #dfd: Screen: wallet_pin
w -> w : derive key pair (//pin_derived_eph_pub//, //pin_derived_eph_priv//) from KDF(Wallet PIN, encrypt_AES(//pin_salt//, Wallet PIN))

w -> w : generate PoP for pin derived ephemeral key - sign(wallet_backend_session_id | //device_pub//)<sub>//pin_derived_eph_priv//</sub>

'newpage

w -> w : generate PoP for wallet app's key - sign(wallet_backend_session_id | //pin_derived_eph_pub//)<sub>//device_priv//</sub>
note right: proof must be built from both the device key and the key derived from the user PIN, might require new proof type

group Remote HSM
w -> w: prepare wallet attestation POP with audience, expiration time and pid_issuer_session_id

w -> w: hash wallet attestation PoP

w -> wb : tls() HTTP POST <UUID, issuer_ID, PoP for pin derived ephemeral key, PoP for wallet app's key, hash of wallet attestation PoP>


wb -> wb: load instance information for UUID
note left: Instance Information: retry counter, //pin_derived_eph_pub//, //device_pub//, security relevant device attributes
wb -> wb: check user pin retry
  note right: request would be refused in case of locked pin
wb -> wb: check security of device against Vulnerability Management information
note left: PIN will not be validated if device is known to be insecure
wb -> wb: check signatures
  note right: user pin retry counter would be increased in case of failed pin signature check, user pin would be locked after threshold is exeeded


wb -> wb: sign hash of wallet attestation PoP with //wb_device_priv//
wb -> w : tls() HTTP 200 <send signed hash of wallet attestation PoP, wallet_backend_session_id>
end

w -> w : assemble wallet attestation PoP
end

w -> i : tls() HTTP POST PAR (PKCE code_challenge, Wallet Attestation + PoP, client_id)
i -> i : verify wallet attestation & PoP \ncheck Wallet Provider solution status on trust list

'newpage

i -> w : tls() HTTP 200 request_uri

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

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

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
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 HSM-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 dev key and key attestation for that key
group Remote HSM
w -> w: prepare DPoP-proof JWT for HSM bound key incl. dpop_nonce, iat and key attestation

w -> w: hash(DPoP-proof JWT for HSM bound key)
w -> wb: tls() HTTP POST <hash of PoP, wallet_backend_session_id>

wb -> wb: check wallet_backend_session_id
wb -> wb: sign hash of PoP with //wb_dpop_priv// (associated with UUID & Issuer_ID)

wb -> w: tls() HTTP 200 <signed hash of proof>

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

w -> i : tls() HTTP POST <Token Request(DPoP Header with proof JWT incl. //wb_dpop_pub// and key attestation, authorization code, PKCE code_verifier)>

i -> i : lookup authorization code\n verify PKCE challenge\n verify DPoP proof\n verify key attestation for DPoP proof
i -> i : create refresh token bound to //wb_dpop_priv// in JWT format with\n eID data symmetrically encrypted with //pp_data// and its expiration date\n and sign the refresh token JWT with //pp_priv//
i -> i: generate and store dpop_nonce
i -> i : generate Token Response with access and refresh token DPoP bound to //wb_dpop_priv// and fresh dpop_nonce
i -> w : tls() HTTP 200 <Token Response(DPoP nonce header with dpop_nonce, DPoP-bound access_token, DPoP-bound refresh_token)>
note left: The access token and the refresh token are both bound to the same key.

w -> w : store DPoP bound access and refresh token
w -> w: store dpop_nonce
hnote over w #dfd: Screen: success
hnote over w #dfd: Screen: home


@enduml
```

#### [Step-by-Step Description] Issuance of a Refresh Token used as a Seed Credential

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 pid_issuer_session_id from the PID Provider
4. The PID Provider generates a fresh pid_issuer_session_id linked to the
   issuance session
5. The PID Provider returns the pid_issuer_session_id to the Wallet
6. The Wallet obtains fresh wallet_backend_session_id from the Wallet Backend's
   session endpoint.
7. part of an above module
8. part of an above module
9. The User enters the Wallet PIN
10. The Wallet proves possession of the Wallet PIN
    - See "Wallet proving possession of the PIN" module for a detailed
      description of the steps
11. part of an above module
12. part of an above module
13. The Wallet prepares a Wallet Attestation PoP; containing
    - audience
    - expiration time
    - pid_issuer_session_id
14. The Wallet hashes the prepared Wallet Attestation PoP
15. The Wallet sends a request to the Wallet Backend; containing
    - UUID & Issuer_ID
    - PoP for *pin_derived_eph_priv*
    - PoP for *device_priv*
    - Hash of the Wallet Attestation PoP
16. The Wallet Backend checks Wallet Instance.
    - See [Wallet Backend checks the Wallet
      Instance](#wallet-backend-checks-the-wallet-instance) module for a
      detailed description of the steps.
17. part of an above module
18. part of an above module
19. The Wallet Backend validates the PoP for *pin_derived_eph_pub* and
    *device_pub*
20. The Wallet Backend signs the hash of Wallet Attestation PoP with
    *wb_device_priv*
21. The Wallet Backend returns the request to the Wallet; containing:
    - signed hash of Wallet Attestation PoP
22. The Wallet assembles the Wallet Attestation PoP using the signature received
    in a previous step
23. The Wallet sends the Pushed Authorization Request to the PID Provider;
    containing
    - the Wallet Provider's client_id
    - authorization_details for PID
    - a PKCE code_challenge
    - a wallet attestation and proof of possession
24. 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
25. The PID Provider returns a `request_uri` that is bound to the Pushed
    Authorization Request
26. The Wallet sends the Authorization Request; containing the PAR `request_uri`
27. The PID Provider responds with the first step to start the eID process with
    the Wallet, e.g. the tcToken, to authenticate the user.
28. Further communication is exchanged to perform the eID process
29. The user provides the eID PIN to the Wallet.
30. Further communication is exchanged to perform the eID process
31. 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.
32. The PID Provider responds to the Wallet with an Authorization Response;
    containing the authorization code.
33. The Wallet generates (and stores) a placeholder DPoP proof with a generic
    (not HSM-bound) keypair to trigger an error response from the Token endpoint
    necessary to retrieve the `dpop_nonce`.
34. The Wallet sends a Token Request to the PID Provider; containing the
    placeholder DPoP proof.
35. The PID Provider generates and stores a `dpop_nonce`.
36. The PID Provider responds with the expected error "use_dpop_nonce";
    containing the `dpop_nonce` to be used from now in the DPoP nonce header.
37. The Wallet extracts and stores the `dpop_nonce`.
38. The Wallet now prepares the actual DPoP-proof JWT for the HSM-bound
    `wb_dpop_pub` including the `dpop_nonce` and `iat`.
39. The Wallet hashes the DPoP proof.
40. The Wallet sends a request to the Wallet Backend to sign the hash of the
    DPoP-proof for the HSM bound key; containing
    - hash of the PoP for the HSM bound key
    - `wallet_backend_session_id`
41. The Wallet Backend validates the `wallet_backend_session_id` and loads
    session context
42. The Wallet Backend signs the hash of the PoP for the HSM bound key with
    *wb_dpop_priv* (associated with UUID & Issuer_ID) from the HSM
43. The Wallet Backend returns the signed hash of the PoP for the HSM bound key
    to the Wallet.
44. The Wallet assembles the DPoP-proof for the HSM bound key using the
    signature received in a previous step
45. The Wallet sends a Token Request to the PID Provider; containing:
    - a DPoP Header with the DPoP-proof JWT incl. `wb_dpop_pub`
    - the authorization code from Authorization Response
    - the PKCE code_verifier matching the code_challenge from Authorization
      Request
    - key attestation for `wb_dpop_pub`
46. The PID Provider matches the code, verifies the PKCE `code_verifier` to the
    previously received `code_challenge` and verifies the DPoP proof.
47. The PID Provider then generates an access token and a refresh token bound to
    the DPoP key *wb_dpop_priv* in JWT format, signed with *pp_priv*;
    containing:
    - the eID data encrypted with *pp_data*
    - the expiration date of the refresh token
48. The PID Provider generates and stores a fresh `dpop_nonce`.
49. The PID Provider generates a Token Response; containing
    - DPoP-bound access token (bound to *wb_dpop_priv*)
    - DPoP-bound refresh token (bound to *wb_dpop_priv*)
    - a c_nonce
    - a fresh `dpop_nonce` in the DPoP nonce header
50. The PID Provider sends the Token Response to the Wallet
51. The Wallet stores the access and the refresh token.
52. The wallet stores the `dpop_nonce`.

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

### Issuance of a Batch of PIDs

#### [Sequence Diagram] Issuance of a Batch of PIDs

```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 Batch Credential Issuance over OpenID4VCI

participant u order 1[
                PID Holder
                ----
                ""PIN: (//user_pin//)""
            ]
participant w  order 3[
                User's EUDI Wallet Instance\
                (eID-Client)
                ----
                ""Device Key: (//device_pub//, //device_priv//)""
                ""Wallet Attestation bound to //wb_device_pub//""
                ""PIN Salt: //pin_salt//""
            ]
participant wb  order 2[
                User's EUDI Wallet Backend
                ----
                ""Long-term Key: (//wb_attestation_pub//, //wb_attestation_priv//)""
                ""Long-term Key: (//wb_device_pub//, //wb_device_priv//)""
            ]
participant i  order 4[
                PID Provider
                (eService+eID Server)
                ----
                ""Long-term Key: (//pp_pub//, //pp_priv//)""
                ""eID data encryption Key: (//pp_data//)""
            ]


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 Batch Credentials

group check pin and generate batch keys
w -> i : tls() HTTP POST </session_endpoint> pid_issuer_session_id
i -> i : generate and store pid_issuer_session_id
i -> w : tls() HTTP 200 <pid_issuer_session_id>

w -> wb: tls() HTTP POST </session_endpoint> wallet_backend_session_id
wb -> wb : generate and store wallet_backend_session_id
wb -> w : tls() HTTP 200 <wallet_backend_session_id>

u --> w: enter Wallet PIN
hnote over w #dfd: Screen: wallet_pin
w -> w : derive key pair (//pin_derived_eph_pub//, //pin_derived_eph_priv//) from KDF(Wallet PIN, encrypt_AES(//pin_salt//, Wallet PIN))
w -> w : generate PoP for pin derived ephemeral key - sign(wallet_backend_session_id | //device_pub//)<sub>//pin_derived_eph_priv//</sub>
w -> w : generate PoP for wallet app's key - sign(wallet_backend_session_id | //pin_derived_eph_pub//)<sub>//device_priv//</sub>
note left: proof must be built from both the device key and the key derived from the user PIN, might require new proof type

w -> wb : tls() HTTP POST <CredentialRequest(UUID, issuer_ID, PoP for pin derived ephemeral key, PoP for wallet app's key)>

'newpage

wb -> wb: load instance information for UUID
note left: Instance Information: retry counter, //pin_derived_eph_pub//, //device_pub//, security relevant device attributes
wb -> wb: check user pin retry
  note right: request would be refused in case of locked pin
wb -> wb: check security of device against Vulnerability Management information
note left: PIN will not be validated if device is known to be insecure
wb -> wb: check signatures
  note right: user pin retry counter would be increased in case of failed pin signature check, user pin would be locked after threshold is exeeded

wb -> wb : generate cryptographic seed (c_seed) for batch credentials and associate with issuer_ID
wb -> wb : derive X key pairs (incl. key IDs) (keyIDx, (//batch_kb_X_pub//, //batch_kb_X_priv//)) deterministically from c_seed

wb -> wb : assemble CloudWalletBatchKey claim with X tuples (keyIDx, //batch_kb_X_pub//) and sign with //wb_attestation_priv//



wb -> w : tls() HTTP 200 <signed CloudWalletBatchKey, wallet_backend_session_id>

group Remote HSM
w -> w: generate wallet attestation POP with audience, expiration time, CloudWalletBatchKey and pid_issuer_session_id

w -> w: hash wallet attestation PoP

w -> wb : tls() HTTP POST <hash of wallet attestation PoP, wallet_backend_session_id>

'newpage

wb -> wb: validate wallet_backend_session_id and load session context
wb -> wb: sign hash of wallet attestation PoP with //wb_device_priv//
wb -> w : tls() HTTP 200 <signature for hash of wallet attestation PoP>

w -> w : assemble wallet attestation PoP with signature
end
end

group PID batch issuance

alt No //or// stale DPoP nonce
w -> w : generate placeholder DPoP proof with generic (not HSM-bound) keypair

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")>

w -> w: store dpop_nonce
end

group Remote HSM

'generate DPoP proof with dev key
w -> w: prepare DPoP-proof JWT for HSM bound key incl. dpop_nonce

w -> w: hash(DPoP-proof JWT for HSM bound key)
w -> wb: tls() HTTP POST <hash of PoP, wallet_backend_session_id>

wb -> wb: check wallet_backend_session_id
wb -> wb: sign hash of PoP with //wb_dpop_priv// (associated with UUID & Issuer_ID)

wb -> w: tls() HTTP 200 <signed hash of proof>

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

  w -> i : tls() HTTP POST <Token Request(wallet attestation and wallet attestation PoP,\n DPoP-proof JWT over //wb_dpop_pub//,\n grant_type=refresh_token, DPoP bound refresh token)>
  note left:wallet attestation Header includes Wallet attestation and PoP. DPoP Header includes DPoP proof JWT. refresh_token contains the eID data encrypted with //pp_pub//
  i -> i : verify wallet attestation & PoP \ncheck Wallet Provider solution status on trust list
  i -> i : verify the validity of the refresh token (incl. DPoP-binding)
  i -> i : decrypt refresh token contents with //pp_data// and store user data in session
  i -> i : generate and store dpop_nonce
  i -> i : generate Token Response with DPoP-bound access_token
  i -> w : tls() HTTP 200 <Token Response(DPoP nonce header with dpop_nonce, DPop bound access_token, c_nonce)>

w -> w : prepare X batch credential key PoPs (incl. audience, //batch_kb_X_pub//, c_nonce) and hash them

w -> wb : tls() HTTP POST <BatchSigningRequest(X hashed PoPs, wallet_backend_session_id)>

'newpage

wb -> wb: validate wallet_backend_session_id and load session context

wb -> wb : sign hashed PoPs X with //batch_kb_X_priv//

wb -> w : tls() HTTP 200 <X signed hashed PoPs>

w -> w: assemble X CredentialRequests with signed batch credential key PoPs

'generate DPoP proof with dev key
group Remote HSM


w -> w: prepare DPoP-proof JWT for HSM bound key incl. dpop_nonce

w -> w: hash(DPoP-proof JWT for HSM bound key)
w -> wb: tls() HTTP POST <hash of PoP, wallet_backend_session_id>

wb -> wb: check wallet_backend_session_id
wb -> wb: sign hash of PoP with //wb_device_priv// (associated with UUID & Issuer_ID)

wb -> w: tls() HTTP 200 <signed hash of proof>

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

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 <Batch Credential Request (DPoP Header with proof, X CredentialRequests, credential_response_encryption object, DPoP-bound access_token)>

i -> i : validate DPoP-bound access_token and check signatures of the CredentialRequest proofs

note left: ensure that the //batch_kb_X_pub// from the CredentialRequests match to the public keys in the CloudWalletBatchKey claim from the wallet attestation PoP

alt #ddf ISO mdoc
  i -> i : create mdoc with eID data and //batch_kb_X_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 <Batch Credential Response(DPoP nonce Header with dpop_nonce, JWT(<color blue>mdoc</color>))>
else #dfd SD-JWT VC
  i -> i : create SD-JWT VC with eID data and //batch_kb_X_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 <Batch Credential Response(DPoP nonce Header with dpop_nonce, JWT(<color blue>SD-JWT VC, Disclosures</color>))>
end

w -> w : decrypt batch credential response JWT and retrieve PID
w -> w: match keyIDx from CloudWalletBatchKey claim to SD-JWT/mdoc Credentials by their respective public key (//batch_kb_X_pub//) and store as tuple in BatchCredentialStore with issuer_ID
w -> w: store dpop_nonce

end

@enduml
```

#### [Step-by-Step Description] Issuance of a Batch of PIDs

1. The user opens and unlocks the Wallet.
2. The Wallet requests issuance of PID Batch Credentials.
3. The Wallet requests fresh wallet_backend_session_id
4. The Wallet Backend generates and links it to the session
5. The Wallet Backend returns the wallet_backend_session_id to the Wallet
6. The Wallet requests a fresh pid_issuer_session_id from the Wallet Backend
7. The Wallet Backend generates a fresh wallet_backend_session_id linked to the
   session
8. The Wallet Backend returns the pid_issuer_session_id to the Wallet
9. The user enters the Wallet PIN.
10. The Wallet proves possession of the Wallet PIN
    - See "Wallet proving possession of the PIN" module for a detailed
      description of the steps
11. part of an above module
12. part of an above module
13. The Wallet sends a Credential Request to the Wallet Backend; containing
    - the UUID & the Issuer_ID,
    - the PoP for `pin_derived_eph_priv` and
    - the PoP for `device_priv`
14. The Wallet Backend checks Wallet Instance.
    - See [Wallet Backend checks the Wallet
      Instance](#wallet-backend-checks-the-wallet-instance) module for a
      detailed description of the steps.
15. part of an above module
16. part of an above module
17. The Wallet Backend validates the PoP for *pin_derived_eph_pub* and
    *device_pub*.
18. The Wallet Backend generates a cryptographic seed (c_seed) for the batch
    credential keys and associates it with Issuer_ID
    - Each batch of credentials uses it's own c_seed, previous c_seeds are
      discarded when a new batch of credentials for a specific Issuer are
      requested
19. The Wallet Backend deterministically derives the required number of key
    pairs incl. key IDs from c_seed
    - A mechanism for key derivation will be defined later
20. The Wallet Backend assembles a claim called CloudWalletBatchKey containing
    the public part of the just generated key pairs and the respective key IDs
    and signs the claim with *wb_attestation_priv*.
21. The Wallet Backend returns the request to the Wallet; containing
    - the signed CloudWalletBatchKey
22. The Wallet prepares a Wallet Attestation PoP containing
    - the audience,
    - the signed CloudWalletBatchKey claim and
    - the pid_issuer_session_id.
23. The Wallet hashes the Wallet Attestation PoP.
24. The Wallet sends a signing request to the Wallet Backend containing
    - hash of the Wallet Attestation PoP
    - wallet_backend_session_id
25. The Wallet Backend validates the wallet_backend_session_id and loads the
    session context.
26. The Wallet Backend signs the hash of the Wallet Attestation PoP with the
    respective *wb_device_priv*.
27. The Wallet Backend returns the request to the Wallet incl. the signed hash
    of the Wallet Attestation PoP.
28. The Wallet assembles the Wallet Attestation PoP using the signature received
    in a previous step.
29. The Wallet generates (and stores) a placeholder DPoP proof with a generic
    (not HSM-bound) keypair to trigger an error response from the Token endpoint
    necessary to retrieve the `dpop_nonce`.
30. The Wallet sends a Token Request to the PID Provider; containing the
    placeholder DPoP proof.
31. The PID Provider generates and stores a `dpop_nonce`.
32. The PID Provider responds with the expected error "use_dpop_nonce";
    containing the `dpop_nonce` to be used from now in the DPoP nonce header.
33. The Wallet extracts and stores the `dpop_nonce`.
34. The Wallet prepares the DPoP-proof JWT for the HSM-bound
    `wb_attestation_pub` including the `dpop_nonce` and `iat`.
35. The Wallet hashes the DPoP proof.
36. The Wallet sends a request to the Wallet Backend to sign the hash of the
    DPoP-proof for the HSM bound key containing
    - a hash of the PoP for the HSM bound key
37. The Wallet Backend validates the wallet_backend_session_id and loads the
    session context.
38. The Wallet Backend signs the hash of the PoP for the HSM bound key with
    *wb_device_priv* (associated with UUID & Issuer_ID) from the HSM.
39. The Wallet Backend returns the signed hash of the PoP for the HSM bound key
    to the Wallet.
40. The Wallet assembles the DPoP-proof for the HSM bound key using the
    signature received in a previous step.
41. The Wallet sends a Token Request to the PID Provider containing
    - the Wallet Attestation + PoP in the wallet attestation Header,
    - the DPoP-proof JWT over `wb_attestation_pub`,
    - the grant_type "refresh_token",
    - the DPoP-bound refresh token
42. 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
43. The PID Provider verifies the validity of the refresh token (incl.
    DPoP-binding).
44. The PID Provider decrypts the refresh token contents with //pp_data// and
    stores the users identity attributes in the session.
45. The PID Provider generates and stores a `dpop_nonce`.
46. The PID Provider generates a Token Response with a DPop bound access token.
47. The PID Provider returns a Token Response to the Wallet containing
    - the DPoP bound access_token and
    - the c_nonce
    - a fresh `dpop_nonce` in the DPoP nonce header.
48. The Wallet prepares the required number of PoP (incl. audience and
    respective public key) for the batch credential keys and hashes them.
49. The Wallet sends a BatchSigningRequest to the Wallet Backend containing
    - the required number of hashed batch credential key PoPs and
    - the wallet_backend_session_id.
50. The Wallet Backend validates the wallet_backend_session_id and loads the
    session context.
51. The Wallet Backend signs the hashed batch credential key PoPs with the
    respective *batch_kb_X_priv*.
52. The Wallet Backend returns the request to the Wallet incl. the signed hashes
    of the batch credential key PoPs.
53. The Wallet assembles the required amount of CredentialRequests containing
    the signed batch credential key PoPs.
54. The Wallet prepares the DPoP-proof JWT for the HSM-bound //dev// key
    including the `dpop_nonce` and `iat`.
55. The Wallet hashes the DPoP proof.
56. The Wallet sends a request to the Wallet Backend to sign the hash of the
    DPoP-proof for the HSM bound key containing
    - a hash of the PoP for the HSM bound key and
    - the wallet_backend_session_id.
57. The Wallet Backend validates the wallet_backend_session_id and loads the
    session context.
58. The Wallet Backend signs the hash of the PoP for the HSM bound key with
    *wb_dpop_priv* (associated with UUID & Issuer_ID) from the HSM.
59. The Wallet Backend returns the signed hash of the PoP for the HSM bound key
    to the Wallet.
60. The Wallet assembles the DPoP-proof for the HSM bound key using the
    signature received in a previous step.
61. The Wallet generates a new ephemeral keypair (*cre_eph_pub*,
    *cre_eph_priv*).
62. 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
63. The Wallet sends a BatchCredentialRequest to the PID Provider containing
    - DPoP proof JWT
    - required amount of CredentialRequests
    - `credential_response_encryption` object
    - DPoP bound access_token
64. The PID Provider validates the DPoP bound access_token and checks the
    signatures of the CredentialRequests.
    - The PID Provider has to ensure that the *batch_kb_X_pub* from the
      CredentialRequests match to the public keys in the CloudWalletBatchKey
      claim from the Wallet Attestation PoP.
65. **(mdoc)** The PID Provider creates the mdoc containing
    - the issuerAuth with the *batch_kb_X_pub* as deviceKey and hashes of the
      eID data,
    - the eID data as NameSpaceBytes and
    - the status management information
66. **(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 credential to the payload.
67. The PID Provider generates and stores a fresh `dpop_nonce`.
68. **(mdoc)** The PID Provider sends the Credential Response JWT containing
    - the required amount of PID credentials as mdoc.
69. **(SD-JWT)** The PID Provider creates SD-JWT VC containing
    - the SD-JWT with the *batch_kb_X_pub* as confirmation claim and hashes of
      the eID data,
    - the eID data as Disclosures and
    - the status management information
70. **(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 credential to the payload.
71. The PID Provider generates and stores a fresh `dpop_nonce`.
72. **(SD-JWT)** The PID Provider sends the Credential Response JWT containing
    - the required amount of PID credentials as SD-JWT VC.
73. The Wallet decrypts the Credential Response JWT using the *cre_eph_priv*.
74. The Wallet matches the key IDs (from the CloudWalletBatchKey claim) to the
    public keys in the Credential Response by their respective public keys and
    stores them as tuple in a BatchCredentialStore with the issuer_ID.
75. The Wallet extracts and stores the `dpop_nonce`.

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

### Credential Presentation

#### [Sequence Diagram] Credential Presentation

[User Journey: PID Presentation - Issuer Signed -
Cloud](../user_journeys/PID-IssuerSigned-cloud-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

participant u order 1[
                PID Holder
                ----
                ""PIN: (//user_pin//)""
            ]
participant b order 2 [
   Browser App
   (same device)
]
participant v order 3[
                Relying Party
                ----
                ""Long-term Key: (//rp_pub//, //rp_priv//)""
]

participant w  order 4[
                User's EUDI Wallet Instance\
                (eID-Client)
                ----
                ""Device Key: (//device_pub//, //device_priv//)""
                ""Wallet Attestation bound to //wb_device_pub//""
                ""PIN Salt: //pin_salt//""
            ]
participant wb  order 5[
                User's EUDI Wallet Backend
                ----
                ""Long-term Key: (//wb_attestation_pub//, //wb_attestation_priv//)""
                ""Long-term Key: (//wb_device_pub//, //wb_device_priv//)""
            ]

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>sessionId</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>sessionId</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

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

w -> w: pick batch credential tuple (Credential, keyIDx) from batch credential store

'newpage

alt #ddf ISO mdoc
  w -> w : prepare mdoc presentation according to <presentation_definition> by removing unnecessary NameSpaceBytes
  w -> w : calculate SessionTranscript (mDocGeneratedNonce, client_id, responseUri, nonce) and generate deviceAuth payload and hash
else #dfd 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, hash of SD-JWT and disclosures) and hash
end

group check pin & sign in remote HSM

w -> wb: tls() HTTP POST </session_endpoint> wallet_backend_session_id
wb -> wb : generate and store wallet_backend_session_id
wb -> w : tls() HTTP 200 <wallet_backend_session_id>

u <--> w : input Wallet PIN
hnote over w #dfd: Screen: wallet_pin

w -> w : generate key pair (//pin_derived_eph_pub//, //pin_derived_eph_priv//) from KDF(Wallet PIN, encrypt_AES(//pin_salt//, Wallet PIN))

w -> w : generate PoP for pin derived ephemeral key - sign(wallet_backend_session_id | //device_pub//)<sub>//pin_derived_eph_priv//</sub>
w -> w : generate PoP for wallet app's key - sign(wallet_backend_session_id | //pin_derived_eph_pub//)<sub>//device_priv//</sub>

w -> wb : tls() HTTP POST <UUID, issuer_ID, PoP for pin derived ephemeral key, PoP for wallet app's key, hash of KB-JWT/deviceAuth , keyIDx>

'newpage

wb -> wb: load instance information for UUID
note left: Instance Information: retry counter, //pin_derived_eph_pub//, //device_pub//, security relevant device attributes
wb -> wb: check user pin retry
  note right: request would be refused in case of locked pin
wb -> wb: check security of device against Vulnerability Management information
note left: PIN will not be validated if device is known to be insecure
wb -> wb: check signatures
  note right: user pin retry counter would be increased in case of failed pin signature check, user pin would be locked after threshold is exeeded

wb -> wb: identify c_seed with issuer_ID and load
wb -> wb: deterministically regenerate (//batch_kb_X_pub//, //batch_kb_X_priv//) from c_seed and keyIDx
wb -> wb: sign hash of KB-JWT/deviceAuth hash with //batch_kb_X_priv//
wb -> w : tls() HTTP 200 <signed KB-JWT/deviceAuth hash>
end

alt #ddf ISO mdoc
  w -> w : assemble deviceAuth and build presentation with issuerSigned and deviceSigned(deviceAuth)
else #dfd 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_definition
w -> w : add optionally other presentations according to the presentation_definition
w -> w: delete used batch credential and matching keyIDx

'newpage

w -> v : tls() HTTP POST <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>sessionId</color>

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

alt #ddf ISO mdoc
  v -> v : verify contents of <vp_token>:\n- verify mdoc issuerAuth PID\n- verify deviceAuth with //batch_kb_X_pub// from issuerAuth\n- calculate and validate correct SessionTranscript
else #dfd SD-JWT VC
  v -> v : verify contents of <vp_token>:\n- verify SD-JWT PID\n- verify KB-JWT with //batch_kb_X_pub// 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
```

#### [Step-by-Step Description] Credential 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 an ephemeral key pair (e.g., `rp_eph_pub`, `rp_eph_priv`)
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 (e.g.,
   `openid4vp://authorize?client_id=..&request_uri=https://rp.example.com/oidc/request/1234`);
   a cookie with the browser sessionId is set
7. The user clicks on the link
8. The RP website navigates to the custom scheme link to launch the Wallet
9. The user unlocks the Wallet (see notes below)
10. The Wallet sends a GET request to the RP's Authorization Request endpoint
    (e.g., `https://rp.example.com/oidc/request/1234`)
11. The Wallet retrieves the Authorization Request from the RP website
12. The Wallet 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. The Wallet picks a batch credential tuple (Credential incl. possible
    disclosures, keyID) from the batch credential store
15. **(mdoc)** The Wallet prepares an mdoc presentation according to the
    presentation_definition by removing NameSpaceBytes of not disclosed
    attributes.
16. **(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 and hashes the deviceAuthentication structure.
17. **(SD-JWT)** The Wallet generates an SD-JWT VC presentation according to the
    presentation_definition by removing Disclosures of not disclosed attributes.
18. **(SD-JWT)** The Wallet creates the header and payload for the KB-JWT from
    audience, nonce, hash of issuer-signed JWT and Disclosures for signing and
    hashes the payload.
19. The Wallet requests a fresh wallet_backend_session_id from the Wallet
    Backend
20. The Wallet Backend generates a fresh wallet_backend_session_id linked to the
    session
21. The Wallet Backend returns the wallet_backend_session_id to the Wallet
22. The User enters the Wallet PIN
23. The Wallet proves possession of the Wallet PIN
    - See "Wallet proving possession of the PIN" module for a detailed
      description of the steps
24. The Wallet signs over the wallet_backend_session_id and the device-bound
    public key *device_pub* using the key *pin_derived_eph_priv*
25. The Wallet signs over the wallet_backend_session_id and the Wallet PIN
    derived public key *pin_derived_eph_pub* using the key *device_priv*
26. The Wallet sends a signing request to the Wallet Backend; containing
    - UUID & issuer_ID
    - PoP for pin_derived_eph_priv
    - PoP for device_priv
    - hash of KB-JWT/deviceAuth
    - keyID (of the respective key that should be used to sign)
27. The Wallet Backend checks Wallet Instance.
    - See [Wallet Backend checks the Wallet
      Instance](#wallet-backend-checks-the-wallet-instance) module for a
      detailed description of the steps.
28. part of an above module
29. part of an above module
30. The Wallet Backend validates the PoP for *pin_derived_eph_pub* and
    *device_pub*
31. The Wallet Backend loads the c_seed associated with the issuer_ID
32. The Wallet Backend deterministically regenerates (*batch_kb_X_pub*,
    *batch_kb_X_priv*) from c_seed and keyIDx
    - A mechanism for key derivation will be defined later
33. The Wallet Backend signs the hash of KB-JWT/deviceAuth with the respective
    *batch_kb_X_priv*
34. The Wallet Backend returns the signed hashes of KB-JWT/deviceAuth to the
    Wallet
35. **(mdoc)** The Wallet assembles the deviceAuth from header, payload and
    signature and builds the presentation from deviceAuth and issuerSigned
36. **(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
37. The Wallet creates a VP token and a presentation submission from the
    received credential.
38. Optional: The Wallet can add further presentations
39. The Wallet deletes the used batch credential tuple (credential, keyID)
40. The Wallet sends the VP token and presentation submission to the RP
    (encrypted to the RP's public key *rp_eph_pub*).
41. The RP finds a session with the state and generates a response_code for this
    session
42. The RP returns the redirect_uri with the response_code to the Wallet
43. The Wallet launches the browser with the redirect_uri and response_code.
44. The browser sends the redirect_uri and response code to the RP, attaching
    the browser sessionId as a cookie.
45. The RP looks up whether there exists a session with the sessionId from the
    cookie and a matching response_code
46. **(mdoc)** The RP verifies the PID in the VP token and verifies the
    SessionTranscript calculated from nonce, mDocGeneratedNonce, client_id,
    response_uri.
47. **(SD-JWT)** The RP verifies the SD-JWT PID in the VP token, verifies the
    KB-JWT using the *batch\_kb\_X\_pub* in the SD-JWT, and verifies the nonce
    and audience in the KB-JWT
48. The RP considers the user to be identified in the session context and
    continues the UX flow.

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

## Modules

### Wallet proving possession of the device-bound PIN

These steps are used during X and Y. They are intended to proof possession of
Wallet PIN and ensure that PIN is used only by a certain device.

1. The Wallet generates the key pair (*pin_derived_eph_pub/priv*) derived from
   the Wallet PIN following the steps defined below
2. The Wallet generates and stores a device bound key pair (*device_pub1/priv1*)
3. The Wallet signs the wallet_backend_session_id and the device-bound public
   key *device_pub1* using the key *pin_derived_eph_priv*
    - This is a Proof of Knowledge of the Wallet PIN realized as a Proof of
      Possession
    - The wallet_backend_session_id and the *device_pub1* key are included as
      JWT claims
4. The Wallet signs over the wallet_backend_session_id and the Wallet PIN
   derived public key *pin_derived_eph_pub* using the key *device_priv1*
    - This binds PIN to the device
    - The wallet_backend_session_id and the *pin_derived_eph_pub* key are
      included as JWT claims

#### Derivation of `pin_derived_eph_pub` and `pin_derived_eph_priv`

1. Encrypt Wallet PIN with an AES key bound to the device. This is a
   `pin_secret`, which is used to generate a salt for the KDF in the next step.
   - Could possibly be replaced by the generation & storage of a conventional
     salt (due to differences in AES in iOS/Android)
1. Use `pin_secret` and Wallet PIN in a KDF. This generates a `pin_seed` which
   is a cryptographic secret from the PIN and the salt (`pin_secret`) used as a
   seed for creating the key pair in the next step
1. Use `pin_seed` to seed the EC key generation. This results in
   `pin_derived_eph_pub` and `pin_derived_eph_priv`.

### Wallet Backend checks the Wallet Instance

1. The Wallet Backend loads the Wallet Instance information for UUID
2. The Wallet Backend checks the users Wallet PIN retry counter
    - If the PIN retry counter has exceeded the defined maximum value, the
      request is rejected
3. The Wallet Backend checks the current security state of the Wallet device
   against Vulnerability Management information
    - If the device is no longer secure (e.g. has known vulnerabilities), the
      request is rejected

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

## 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 wallet attestaion PoP to the session and prove its
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:

```html
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:

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

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

### Wallet Backend's Session Endpoint

This endpoint is used by the Wallet to obtain `session_id` from the Wallet
Backend. It is used to 1) bind two PoPs (used to bind the PIN proof to the
device and to prove possession of a PIN) to the session to prove their
freshness, and 2) authenticate the wallet instance throughout a session. 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 Wallet Backend 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"
}
```

### Wallet proving possession of the PIN

#### Generation of a Proof of Knowledge of the Wallet PIN

A PIN-derived ephemeral public key that is needed to validate the signature on
this JWT must be included in the `jwk` header parameter. There must be a JWT
header parameter `typ` with the value being `pin_derived_eph_pub_pop`. The JWT
payload must contain an `aud` claim whose value is equal to the Wallet backend's
Identifier. wallet_backend_session_id must be included in a
`wallet_backend_session_id` parameter.

Below is a non-normative example of a JWT generated as a PoP for pin derived
ephemeral key:

```json
{
  "alg": "...",
  "typ": "pin_derived_eph_key_pop",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "bPP7f...gW_ao",
    "y": "38_Lg...VUCfW"
  }
}.
{
  "wallet_backend_session_id": "123456",
  "aud": "https://pid-issuer.example.com",
  "device_key": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "...",
      "y": "..."
    }
  }
}.[signature by the pin derived ephemeral pub key]
```

The `jwk` claim contains the public key of a PIN-derived ephemeral key pair.

#### Binding PIN to the device

A device public key that is needed to validate the signature on this JWT must be
included in the `jwk` header parameter. There must be a JWT header parameter
`typ` with the value being `device_key_pop`. The JWT payload must contain an
`aud` claim whose value is equal to the Wallet backend's Identifier.
wallet_backend_session_id must be included in a `wallet_backend_session_id`
parameter.

Below is a non-normative example of a JWT, which is a PoP for `device_key`:

```json
{
  "alg": "...",
  "typ": "device_key_pop",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "...",
    "y": "..."
  }
}.
{
  "wallet_provider_session_id": "123456",
  "aud": "https://pid-issuer.example.com",
  "pin_derived_eph_pub": {
    "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "V03QP...LHN53",
    "y": "xjilK...i0_tT"
    }
  },
}.[signature by the device_key]
```

Here, the `jwk` claim contains a public key of a device key pair.

### Passing DPoP key attestation in the token request

The Wallet MUST provide key attestation for the key used in the DPoP proof in
the Token Request as defined in this section.

The DPoP Proof JWT defined in Section 4.2 of RFC 9449 MUST additionally contain
the following parameter:

- `attestation`: REQUIRED. String representing a key attestation JWT as defined
  in (Section 8.2.1 of
  OpenID4VCI)[https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#section-8.2.1-2.3].
  The content of the Key Attestation JWT MUST be conformant to (Annex D of
  OpenID4VCI)[https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#appendix-D.1]

Below is a non-normative example of a DPoP Proof JWT, which contains an
`attestation` parameter in the JOSE Header:

```json
{
  "typ":"dpop+jwt",
  "alg":"ES256",
  "jwk": {
    "kty":"EC",
    "x":"l8tFrhx-34tV3hRICRDY9zCkDlpBhF42UQUfWVAWBFs",
    "y":"9VE4jf_Ok_o64zbTTlcuNJajHmt6v9TDVrU0CdvGRDA",
    "crv":"P-256"
  }
  "attestation" : <key attestation JWT>
}
.
{
  "jti":"-BwC3ESc6acc2lTc",
  "htm":"POST",
  "htu":"https://server.example.com/token",
  "iat":1562262616
}
```

Below is a non-normative example of a key attestation JWT, which was included in
the `attestation` parameter in the JOSE Header in the example above:

```json
{
  "typ": "keyattestation+jwt",
  "alg": "ES256",
  "x5c": ["MIIDQjCCA..."]
}
.
{
  "iss": "<identifier of the issuer of this key attestation>",
  "iat": 1516247022,
  "exp": 1541493724,
  "key_storage": [ "iso_18045_moderate" ],
  "user_authentication": [ "iso_18045_moderate" ],
  "attested_keys": [
    {
      "kty": "EC",
      "crv": "P-256",
      "x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
      "y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
    }
  ]
}
```

## Usability Considerations

### Activation

- The Wallet needs to be initialized on a mandatory basis
- During Activation, the user must set a Wallet PIN
- Having only one Wallet PIN has the advantage that the same PIN (eID PIN
  excluded) could probably also be used for other credentials (also at the same
  LoA). From a UX perspective, this would be a great added value for users.
- The wallet can only be used after successful Activation

### Issuance of a Refresh Token used as a Seed Credential

- 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
- User must confirm the issuing process with the Wallet
- 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 Wallet PIN. The
  distinction between the two PINs should be easier for users than the
  distinction between eID PIN and Wallet PIN
- User can have a PID credential derived from the eID on several end devices at
  the same time

### Presentation

- The device must be online for the PID presentation
- 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 and how this should be implemented.
- 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 enter the Wallet PIN for each PID presentation
- 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: The wallet provider receives information about when the
      user creates a presentation or when the user requests a new credential
      from a new issuer. Apart from this information, the wallet provider does
      not gain any insight into the transaction-specific details.
- 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, if they
      store the public keys used for Batch Credential Issuance.
    - 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, if the PID Provider stores the public keys used for
      Batch Credential Issuance
- 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 using salted hashes inside the MSO/SD-JWT.

## 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: User Binding is achieved by multifactor
  authentication employing a device bound key and a PIN that is validated inside
  a secure area on the Wallet Backend.
- Session Integrity:
    - Issuance:
        - PID Provider and Wallet share a pre-configured trust relationship,
          established through certificate pinning and other mechanisms.
        - Freshness of DPoP proofs required for DPoP binding of Access and
          Refresh Tokens is assured by including issuer provided DPoP nonces,
          see [DPoP Proof
          Replay](https://www.rfc-editor.org/rfc/rfc9449.html#section-11.1),
          [DPoP Proof
          Pre-generation](https://www.rfc-editor.org/rfc/rfc9449.html#section-11.2).
    - 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 041: 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

- 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?