Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issuer Trust Evidence / key attestations for OpenID4VCI #355

Open
paulbastian opened this issue Jun 25, 2024 · 29 comments · May be fixed by #389
Open

Issuer Trust Evidence / key attestations for OpenID4VCI #355

paulbastian opened this issue Jun 25, 2024 · 29 comments · May be fixed by #389
Assignees

Comments

@paulbastian
Copy link
Contributor

In the context of eIDAS 2, we require a Wallet/Issuer Trust Evidence, basically a key attestation made by the Wallet Provider ensuring that keys used for keybinding really reside in a trustworthy key store (called WSCD in eIDAS). In earlier iterations the construct that has so far been called "Wallet Attestation", consisted of two statements:

  • The app/wallet instance is authentic/valid (through app attestation)
  • The key is really is authentic/valid (through key attestation)

After disussions at EIC 2024, we propose to split this up and match with current eIDAS directions, i.e. have two attestations:

  • Wallet Instance Attestation (WIA) -> authenticating the Wallet Instance
  • Issuer/Wallet Trust Evidence (ITE/WTE) -> authenticating the WSCD

The WIA could be tested with Attestation-Based Client Authentication at the PAR or Token Endpoint. What's remaining then is to convey and integrate the ITE/WTE concept to OpenID4VCI.

The proposal is to send the ITE/WTE at the Credential Endpoint, because this is where the keys are transmitted. The easiest and least breaking possibility is to create a new proof type, this could potentially also address other issues like #305 which increase the scalability of batch issuance.

The diagram gives a rough idea:

Diagram

A new proof type could like this:

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: DPoP czZCaGRSa3F0MzpnWDFmQmF0M2JW

{
  "credential_identifier": "CivilEngineeringDegree-2023",
  "proofs": {
    "ite": {
      "attestation" : "<base64encoded JWT signed by wallet provider>",
      "proof" : "<JWT proof for cnf key inside the attestation>"
    }
  }
}
{
  "typ": "ite+jwt",
  "alg": "ES256",
  "x5c":  <trust chain of the wallet provider>
}
.
{
  "iss": "<client_id of Wallet Provider>",
  "iat": 1516247022,
  "exp": 1541493724,
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
      "y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
    },
    "key_type": "strong_box",
    "user_authentication": "system_pin",
  },
  "device_keys" : [ //optional
      "eyJ0eXAiOiJvcGVuaWQ0dmNpL...Lb9zioZoipdP-jvh1WlA",
      "eyJraWQiOiJkaWQ6ZXhhbXBsZ...KPxgihac0aW9EkL1nOzM"
    ].
  "status" : { //optional
    "status_list" : {
      "uri" : "<uri>",
      "idx" : <index>
    }
  }
}

The ITE may include device_keys public key array that the Credential Issuer could trust directly without additional PoPs. The ITE may also include status information to communicate possible WSCD compromise.

Lets start the discussion :)

@babisRoutis
Copy link
Contributor

babisRoutis commented Jul 8, 2024

Hi @paulbastian

To my understanding with your proposal

  • ite/attestation contains the WTE, signed by wallet provider, includes wallet instance key in cnf/jwk and and array of device_keys
  • ite/proof is the PoP JWT for the wallet instance key, found inside the WTE

If so, I think there is the following practical problem:
Let's assume that a wallet wants to issue two credentials (different configuration ids), from the same issuer, both of them requiring device_keys.
Wallet will provision somehow a single WTE with two device_keys. It is not clear to me how each individual credential request will indicate a specific key inside the device_key array.

@tlodderstedt
Copy link
Collaborator

I think this issue is about different things:

  1. Split wallet attestation into wallet instance attestation and issuer trust evidence (basically an interoperable key attestation)
  2. Use the wallet instance attestation instead of the wallet attestation at the token endpoint to authenticate with the issuer
  3. Use the issuer trust evidence with the credential request (along with the PoP for the respective key)
  4. an optimiziation to be able to provide multiple keys without the need for PoP for each individual key

I think the issuer trust evidence (3) could be provided as part of the proof. I'm thinking of an additional JOSE header, just like x5c.
I also think the optimization (4) could utilize an additional request parameter, e.g. bulk_key_attestation, where the new JOSE header could refer to an individual key in the structure.

@tlodderstedt
Copy link
Collaborator

tlodderstedt commented Jul 18, 2024

After the discussion in the WG meeting on Tue, I have come to the following conclusions:

I think it suffices to add a new header attestation with the key attestation to the existing proof types. For the jwt proof type that could look like this:

{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "attestation" : ["<base64encoded JWT signed by wallet provider>","<optional additional JWTs>"]
}.{
  "aud": "https://credential-issuer.example.com",
  "iat": 1701960444,
  "nonce": "LarRGSbmUPYtRYO6BQ4yn8"
}

The attestation header would contain the key attestation as issued by the wallet provider.

The attestation could:

  1. contain a single cnf key, in which case the credential to be issued would be bound to this key or
  2. contain an array device_keys with one or more device keys, the issuer would issue a credential instance for every entry in the array and would bind the instance to the respective key in the array.

(1) would allow to migrate existing code using the "old" wallet attestations to be used at the credential endpoint and would allow a simple model for issuing individual credentials.
(2) would allow to proof possession and provenance for a batch of credentials at once. Letting the issuer determining the number of instances to be generated based on the device_keys array felt weird on first sight. However, I came to the conclusion that is the way the current proof types work, too. The credential endpoint already expects the proof to determine what key to be used for cryptographic binding. Interestingly that would lead to a situation, where a wallet would pass a proof parameter but receive a batch of credential instances (same holds true for Paul's original proposal).

There is also a possible extension: there is a concept called "Proof of Association" being discussed in the EUDI Wallet space. It allows to proof that two keys are managed by the same security module (aka WSCD). The issuance flow could utilize this concept to minimize the data shared with the wallet backend (privacy) and reduce the calls needed to create key attestations (performance, availability). The wallet app would obtain one attestation for a key serving as trust anchor (Issuer Trust Evidence). Subsequently, the wallet app could create a new key in the local WSCD along with a proof of possession between the ITE key and the new key. This would basically be a static assertion and could be treated as part of a chain of trust. That's why I think it could just be added to the attestation header as another JWT.

The trust would then be from the ITE via the PoA to the PoP for the new key.

@Sakurann
Copy link
Collaborator

discussed in the WG during the calls in the week of july 15th.

as the next steps, there seems to be rough consensus on the following points (from Torsten's earlier comment):

  1. Split wallet attestation into wallet instance attestation and key attestation
  2. Use the wallet instance attestation instead of the wallet attestation at the token endpoint to authenticate with the issuer.

Agree to focus discussion in this issue on
3. Use the key attestation with the credential request when one key is being attested

open a new issue to discuss
4. an optimization to be able to provide multiple keys without the need for PoP for each individual key on top of the point 3.

@Sakurann
Copy link
Collaborator

to elaborate in a bit more layman terms what has been discussed/proposed on the call for point 3:

a. there is device key A to which wallet instance wants an issued credential to be bound
b. wallet instance asks the wallet backend to attest that key A
c. wallet backend issues a key attestation, which is a JWT that contains key A in a cnf claim
d. wallet instance puts creates a proof where key attestation from step c. is in the header and the proof JWT is signed using key A (PoP for key attestation)
e. issuer validates the proof and issues a credential that is bound to key A

@alenhorvat
Copy link

How this maps to today's x509 issued by QTSPs? Such mechanisms do exist today in the x509 world.

@ssanchocanela
Copy link

@tlodderstedt where should the WTE be presented to an issuer as part of the request to get another attestation like a Diploma?

  1. To the authorization server?
  2. Together with the authorization token at the credential endpoint? --> using the "attestation" header

@babisRoutis
Copy link
Contributor

@tlodderstedt where should the WTE be presented to an issuer as part of the request to get another attestation like a Diploma?

1. To the authorization server?

2. Together with the authorization token at the credential endpoint? --> using the "attestation" header

ARF in annex 1, provides the following short definition

Wallet Instance Attestation (WIA)
Attestation issued by a Wallet Provider to a Wallet Instance with the sole purpose of allowing Relying Parties and Attestation Providers to verify the authenticity and validity of the Wallet Instance

So, I guess that it is WIA that will be presented to the token / PAR endpoint of the Attestation Provider (Credential Issuer in VCI terminology). If so, then probably Attestation-based client authentication could be leveraged.

For WTE there is the following

A signed data structure provided by the Wallet Provider to a Wallet Instance during the Wallet Instance activation process, allowing the Wallet Instance to inform Attestation Providers about the properties of the Wallet Instance and (one of) its WSCD(s) and to prove various associations.

Also in annex 2 there are several WTE related requirements. Notably WTE-25:

The common OpenID4VCI protocol SHALL enable a Wallet Instance to transfer the proofs of association and possession mentioned in WTE_19 to a PID Provider or Attestation Provider.
Note: These three proofs MAY be implemented as a single cryptographic proof.

My understanding is that the present issue discusses the options to implement this requirement. That is, WTE is presented somehow to Credential Issuer Endpoint.

@andprian
Copy link

Hello all, I have listed a few requirements that are important for us in the EAA issuance process:

  1. The Issuer must be able to indicate what are the security requirements that must be fulfilled in order for him to issue a specific Credential (type of WSCD, authentication factors constraints, cryptographic constraints, LoA to be achieved).
  2. For every public key the Issuer includes in an attestation, he must be able to verify a a PoP of the private key associated. Therefore the requirement for a PoP is mandated (or not) by the attestation format. This is how we interpret the “optional character” of the PoP.
  3. If the Wallet asks for multiple Credentials from the Issuer, he must be able to provide one PoP for each Credential if its format is expected to embed a public key.
  4. If the Wallet requests for a public key to be embedded in a Credential, he must provide context for that key (see KeyInfo below).
  5. If the Wallet requests for a public key to be embedded in a Credential, he must provide information for the WSCD hosting the private key associated (see WSCDInfo below).
  6. The KeyInfo and WSCDInfo must be attested by the ITE key or the Wallet Provider key, according to the expected LoA

WSCDInfo contains:

  • Type: Remote/Local/Hybrid
  • Capabilities : User Authentication Methods per category (knowledge, possession, inherence..), CryptoEngine (HSM, StrongBox, Software, TEE, SecureEnclave, CardLet+..), CryptoAlgo
  • ….

KeyInfo contains:
• Configuration as an instantiation of the WSCD capabilities (authentication method, CryptoEngine, CryptoAlgo…)
• Lifetime
• PublicKey

@tlodderstedt
Copy link
Collaborator

@alenhorvat I have never seen key attestations in the QTSP context. Can you please refer to solutions for this problem in the x.509 world?

@tlodderstedt
Copy link
Collaborator

@ssanchocanela WTE/ITEs shall be presented with the credential request (at the issuer). The WIA shall be presented to the AS with the token request.

@tlodderstedt
Copy link
Collaborator

@andprian thanks a lot!
I think the PoP requirements are fulfilled by credential request as is today. This issue is about adding the key attestation (WSCD info) to the process. Regarding your examples: are you sure we should do it on this level of detail? How would the issuer use this information? I was assuming the issuer would state something along the lines of "the WCSD must be good for LOA high". WDYT?

@alenhorvat
Copy link

@alenhorvat I have never seen key attestations in the QTSP context. Can you please refer to solutions for this problem in the x.509 world?

In cryptography, X.509 is an International Telecommunication Union (ITU) standard defining the format of public key certificates.

In other words: x509 cert is a public key attestation :) And they are used quite frequently today.

@alenhorvat
Copy link

You can, of course, express it in different formats. Here we mapped the eidas v1 x509 cert to a W3C VC data model:
https://code.europa.eu/ebsi/json-schema/-/tree/main/schemas/vcdm2.0/key-attestations?ref_type=heads

@tlodderstedt
Copy link
Collaborator

split the discussion about the optimization to #368

@tlodderstedt
Copy link
Collaborator

@alenhorvat this issue is about key attestations. My question was: Where QTSPs use key attestations today?

@tlodderstedt
Copy link
Collaborator

tlodderstedt commented Jul 23, 2024

Summary: after we have split the optimization from this issue, the focus is on

  • adding the wallet attestation to the token endpoint (already exists in HAIP)
  • integration of key attestation to the credential endpoint (different syntax proposed)
  • adding metadata giving rise to the issuer's requirements re key attestations

@tlodderstedt
Copy link
Collaborator

tlodderstedt commented Jul 23, 2024

Example of a simple, interoperable key attestation that would go into a new header attestation parameter in jwt proof type:

{
  "typ": "ite+jwt",
  "alg": "ES256",
  "x5c":  <trust chain of the wallet provider>
}
.
{
  "iss": "<client_id of Wallet Provider>",
  "iat": 1516247022,
  "exp": 1541493724,
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
      "y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
    },
    "key_type": "strong_box",
    "user_authentication": "system_pin",
  }.
  "status" : { //optional
    "status_list" : {
      "uri" : "<uri>",
      "idx" : <index>
    }
  }
}

@tlodderstedt
Copy link
Collaborator

Paul and Torsten agreed on this proposal to add the key attestation to the existing JWT proof type:

{
  "typ": "openid4vci-proof+jwt",
  "alg": "ES256",
  "attestation" : ["<base64encoded JWT signed by wallet provider>","<optional additional JWTs>"]
}.{
  "aud": "https://credential-issuer.example.com",
  "iat": 1701960444,
  "nonce": "LarRGSbmUPYtRYO6BQ4yn8"
}

For the CWT proof type, we could add a similar COSE header.

@Sakurann
Copy link
Collaborator

Sakurann commented Jul 23, 2024

for CWT, we should first discuss if we are removing it or not #341

what we have in HAIP now: https://openid.github.io/oid4vc-haip-sd-jwt-vc/openid4vc-high-assurance-interoperability-profile-sd-jwt-vc-wg-draft.html#section-4.3.1-3.1.1

@F-Node-Karlsruhe @dlongley do you need a mechanism for key attestation that is being discussed in this issue for ldp_vc proof type as well?

@Sakurann
Copy link
Collaborator

Sakurann commented Jul 23, 2024

in the wg call, agreed to do two PRs

  1. define a new header parameter attestation for jwt proof type (array), and a schema of a jwt that goes into that header parameter. add issuer metadata where issuer indicates its requirements
  2. move wallet attestation schema from HAIP to VCI and see what from already defined in HAIP can be reused for key attestations

@dlongley
Copy link
Contributor

dlongley commented Jul 23, 2024

@Sakurann,

do you need a mechanism for key attestation that is being discussed in this issue for ldp_vc proof type as well?

Hmm, I would expect that either the mechanisms being discussed here could be used even if the issued credentials use the ldp_vc proof type or that VCs and VPs could be used to express key attestations, for issuing services to accept. IOW, prior to issuance of one or more VCs, an issuer could include a request for one or more VCs from a wallet that include such attestations, folding this into general (re-)use of the OID4* protocols, instead of requiring an additional specialized feature.

(But, admittedly, I may be missing an important detail for why this approach would not work.)

@andprian
Copy link

@tlodderstedt, I added my comments on PoP keeping in mind that the Credential endpoint will be used for issuing multiple EAA at once and as a reaction to the discussions on this issue that we might not do PoP for all keys. As long as we always keep the possibility to transmit PoP for all private keys associated with EAA, that is ok with me.

For the examples, yes, the Issuer should state what LoA he expects to be reached. But the Issuer also bears a responsability on enforcing the LoA High requirements, especially a PID Provider. He has to make sure the Wallet Instance allows to reach for this level, hence the details he has to receive on the WSCD. If a Wallet supports multiple WSCDs, that could appear in one single ITE listing all the details, while the KeyInfo would reflect what WSCD exactly hosts that specific key. The key lifetime is a way to specify extra constraints that might reduce the validity of the EAA that was initially forseen by the Issuer. The authentication methods are crucial for the key protection. Just to give an example, in France we would not be able to pass certifications if we protect something sensitive with an OTP send via SMS, so it is important that a PID Provider has a say in what authentication factors he accepts.

@Sakurann
Copy link
Collaborator

@dlongley what is a mechanism in ldp_vc that is equivalent to a JWT header? I think all we need to say is that for ldp_vc, put key attestation there.

@Sakurann Sakurann assigned dwaite and ve7jtb and unassigned dwaite Jul 25, 2024
@dlongley
Copy link
Contributor

dlongley commented Jul 25, 2024

@Sakurann,

@dlongley what is a mechanism in ldp_vc that is equivalent to a JWT header? I think all we need to say is that for ldp_vc, put key attestation there.

If I'm understanding correctly, this would be for the ldp_vp (note the one-letter difference, not ldp_vc) feature here:

https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#section-7.2.1.2

And, if I've got that right, what can be said is that the key attestation is to be provided as (or within) a VC that is itself within the VP that is signed by the holder (using said key).

@Sakurann
Copy link
Collaborator

when there is attestation for only one key, isn't it an option to use platform-specific key attestation (like Android Keystore Key Attestation) here?

@ssanchocanela
Copy link

when there is attestation for only one key, isn't it an option to use platform-specific key attestation (like Android Keystore Key Attestation) here?

We are considering to obtain the attestation from Google/Apple as first step when you download the wallet, then present the that attestation as part of the activation process to get the WTE.

@paulbastian
Copy link
Contributor Author

paulbastian commented Jul 30, 2024

I think it's a bad idea, issuers will end up requiring to understand many different attestation formats. These formats will change over time. It's a complexity that many issuers may not be able to handle. That's why wallet provider shall handle those platform specific attestations and issue ITE

@ssanchocanela
Copy link

I think it's a bad idea, issuers will end up requiring to understand many different attestation formats. These formats will change over time. It's a complexity that many issuers may not be able to handle. That's why wallet provider shall handle those platform specific attestations and issue ITE

It is the wallet provider the one the shall verify that attestation from Google or Apple. The attestation can be sent within the proof on the idToken.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants