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

add key attestations #389

Open
wants to merge 48 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
6da765e
first draft for key attestation
paulbastian Sep 6, 2024
876c29c
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Sep 10, 2024
feced43
Apply suggestions from code review
paulbastian Sep 17, 2024
56e26fc
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Sep 20, 2024
7c0baa3
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Sep 20, 2024
a96b09b
Apply suggestions from code review
paulbastian Sep 23, 2024
f5db4bf
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Sep 23, 2024
6e3a118
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Sep 23, 2024
64878e0
use key attestation in JWT proof type
paulbastian Sep 23, 2024
1932f71
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 1, 2024
3c15c3c
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 1, 2024
ef84be4
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 1, 2024
bfa2a26
adding metadata and text for apr
paulbastian Oct 1, 2024
8a8dcfd
text for two methods of using key attestation
paulbastian Oct 3, 2024
42de92f
add new proof type for key attestation
c2bo Oct 3, 2024
1b98041
add document history entry for key attestation
c2bo Oct 3, 2024
23c8762
fix reference for attestation proof type
c2bo Oct 3, 2024
7735e1c
add references to key attestation usage
c2bo Oct 3, 2024
05aa467
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 8, 2024
246e083
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 10, 2024
33612a3
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 10, 2024
4e6dc79
Apply suggestions from code review
paulbastian Oct 10, 2024
1f9e94b
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 10, 2024
1131416
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 10, 2024
f71e748
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 10, 2024
4b3c00d
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
c148e8c
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
4d803c0
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
f9cfdba
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
b004300
Apply suggestions from code review
paulbastian Oct 11, 2024
638cc52
Apply suggestions from code review
paulbastian Oct 11, 2024
3c6bb15
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
02aaaa9
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
0641305
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
5677f13
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 11, 2024
19b7815
simplify text in security consideration
paulbastian Oct 11, 2024
e7c882e
Apply suggestions from code review
paulbastian Oct 14, 2024
00224dc
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 14, 2024
28f282b
Apply suggestions from code review
paulbastian Oct 15, 2024
0fc69ef
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 15, 2024
30f32fc
Apply suggestions from code review
paulbastian Oct 18, 2024
e71e851
guidance to use all attested keys in jwt proof type
paulbastian Oct 21, 2024
996139e
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 22, 2024
799b9d3
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 22, 2024
d840dda
Apply suggestions from code review
paulbastian Oct 24, 2024
77fe221
rename key_type to key_storage_type
paulbastian Oct 24, 2024
e578c84
clarify that key_storage_type and user_authentication values should b…
paulbastian Oct 24, 2024
c20d7f9
Update openid-4-verifiable-credential-issuance-1_0.md
paulbastian Oct 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 125 additions & 3 deletions openid-4-verifiable-credential-issuance-1_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,9 @@ This specification defines the following proof types:

* `jwt`: A JWT [@!RFC7519] is used for proof of possession. When a `proof_type` parameter in a `proof` object is set to `jwt`, it MUST also contain a `jwt` parameter that includes a JWT as defined in (#jwt-proof-type). When a `proofs` object is using a `jwt` proof type, it MUST include a `jwt` parameter with its value being an array of JWTs, where each JWT is formed as defined in (#jwt-proof-type).
* `ldp_vp`: A W3C Verifiable Presentation object signed using the Data Integrity Proof [@VC_Data_Integrity] as defined in [@VC_DATA_2.0] or [@VC_DATA] is used for proof of possession. When a `proof_type` parameter in a `proof` object is set to `ldp_vp`, it MUST also contain an `ldp_vp` parameter that includes a [W3C Verifiable Presentation](https://www.w3.org/TR/vc-data-model-2.0/#presentations-0) defined in (#ldp-vp-proof-type). When a `proofs` object is using a `ldp_vp` proof type, it MUST include an `ldp_vp` parameter with its value being an array of [W3C Verifiable Presentations](https://www.w3.org/TR/vc-data-model-2.0/#presentations-0), where each of these W3C Verifiable Presentation is formed as defined in (#ldp-vp-proof-type).
* `attestation`: A JWT [@!RFC7519] representing a key attestation without using a proof of possession of the cryptographic key material that is being attested. When a `proof_type` parameter in a `proof` object is set to `attestation`, the object MUST also contain an `attestation` parameter that includes a JWT as defined in (#attestation-proof-type).
paulbastian marked this conversation as resolved.
Show resolved Hide resolved

There are two ways to convey key attestation(s) of the cryptographic key material during Credential issuance. For details, see (#keyattestation).

#### `jwt` Proof Type {#jwt-proof-type}

Expand All @@ -813,7 +816,8 @@ The JWT MUST contain the following elements:
* `typ`: REQUIRED. MUST be `openid4vci-proof+jwt`, which explicitly types the key proof JWT as recommended in Section 3.11 of [@!RFC8725].
* `kid`: OPTIONAL. JOSE Header containing the key ID. If the Credential shall be bound to a DID, the `kid` refers to a DID URL which identifies a particular key in the DID Document that the Credential shall be bound to. It MUST NOT be present if `jwk` is present.
* `jwk`: OPTIONAL. JOSE Header containing the key material the new Credential shall be bound to. It MUST NOT be present if `kid` is present.
* `x5c`: OPTIONAL. JOSE Header containing a certificate or certificate chain corresponding to the key used to sign the JWT. This element MAY be used to convey a key attestation. In such a case, the actual key certificate will contain attributes related to the key properties.
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
* `x5c`: OPTIONAL. JOSE Header containing a certificate or certificate chain corresponding to the key used to sign the JWT.
* `key_attestation`: OPTIONAL. JOSE Header containing a key attestation as described in (#keyattestation).
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
* `trust_chain`: OPTIONAL. JOSE Header containing an [@!OpenID.Federation] Trust Chain. This element MAY be used to convey key attestation, metadata, metadata policies, federation Trust Marks and any other information related to a specific federation, if available in the chain. When used for signature verification, the header parameter `kid` MUST be present.

* in the JWT body,
Expand All @@ -824,6 +828,8 @@ The JWT MUST contain the following elements:

The Credential Issuer MUST validate that the JWT used as a proof is actually signed by a key identified in the JOSE Header.

If an `attestation` is provided and successfully validated by the Credential Issuer, it SHOULD return a Credential for each of the keys provided in the `attested_keys` claim of the attestation.
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

@nemqe nemqe Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a requirement that the key doing the signing of the proof must be an attested key from the set of attested_keys, and is that what the "kid" is used below in the example?

I am having trouble finding where this is defined.

kind of a copy comment of: https://github.com/openid/OpenID4VCI/pull/389/files#r1811469557


Cryptographic algorithm names used in the `proof_signing_alg_values_supported` Credential Issuer metadata parameter for this proof type SHOULD be one of those defined in [@IANA.JOSE.ALGS].

Below is a non-normative example of a `proof` parameter (with line breaks within values for display purposes only):
Expand Down Expand Up @@ -865,8 +871,10 @@ Here is another example JWT not only proving possession of a private key but als

```json
{
"typ": "openid4vci-proof+jwt",
"alg": "ES256",
"x5c": [<key certificate + certificate chain for attestation>]
"kid": "0",
"key_attestation": <key attestation in JWT format>
}.
{
"iss": "s6BhdRkqt3",
Expand Down Expand Up @@ -920,6 +928,23 @@ Below is a non-normative example of a `proof` parameter:

```

#### `attestation` Proof Type {#attestation-proof-type}

A key attestation in JWT format as defined in (#keyattestation-jwt).

When a key attestation is used as a proof type, it MUST contain the `c_nonce` value provided by the Credential Issuer in its `nonce` parameter.

Below is a non-normative example of a `proof` parameter (with line breaks within values for display purposes only):

```json
{
"proof_type": "attestation",
"attestation": "<key attestation in JWT format>"
}
```

paulbastian marked this conversation as resolved.
Show resolved Hide resolved
The Credential Issuer SHOULD return a Credential for each of the keys provided in the `attested_keys` claim of the `attestation`.
paulbastian marked this conversation as resolved.
Show resolved Hide resolved

### Verifying Proof {#verifying-key-proof}

To validate a key proof, the Credential Issuer MUST ensure that:
Expand Down Expand Up @@ -1280,6 +1305,10 @@ This specification defines the following Credential Issuer Metadata parameters:
* `credential_signing_alg_values_supported`: OPTIONAL. Array of case sensitive strings that identify the algorithms that the Issuer uses to sign the issued Credential. Algorithm names used are determined by the Credential Format and are defined in (#format-profiles).
* `proof_types_supported`: OPTIONAL. Object that describes specifics of the key proof(s) that the Credential Issuer supports. This object contains a list of name/value pairs, where each name is a unique identifier of the supported proof type(s). Valid values are defined in (#proof-types), other values MAY be used. This identifier is also used by the Wallet in the Credential Request as defined in (#credential-request). The value in the name/value pair is an object that contains metadata about the key proof and contains the following parameters defined by this specification:
* `proof_signing_alg_values_supported`: REQUIRED. Array of case sensitive strings that identify the algorithms that the Issuer supports for this proof type. The Wallet uses one of them to sign the proof. Algorithm names used are determined by the key proof type and are defined in (#proof-types).
* `key_attestations_required`: OPTIONAL. Object that describes the requirement for key attestations as described in (#keyattestation), which the Credential Issuer expects the Wallet to send within the proof of the Credential Request. If the Credential Issuer does not expect a key attestation, this object is absent. If neither of the `key_storage_type`, `user_authentication` and `apr` parameters are present, this object may be empty, indicating that a key attestation without further constraints is required.
* `key_storage_type`: OPTIONAL. Array defining values specified in (#keyattestation-keytypes) accepted by the Credential Issuer.
* `user_authentication`: OPTIONAL. Array defining values specified in (#keyattestation-keytypes) accepted by the Credential Issuer.
* `apr`: OPTIONAL. Array defining values specified in (#keyattestation-apr) accepted by the Credential Issuer.
* `display`: OPTIONAL. Array of objects, where each object contains the display properties of the supported Credential for a certain language. Below is a non-exhaustive list of parameters that MAY be included.
* `name`: REQUIRED. String value of a display name for the Credential.
* `locale`: OPTIONAL. String value that identifies the language of this object represented as a language tag taken from values defined in BCP47 [@!RFC5646]. Multiple `display` objects MAY be included for separate languages. There MUST be only one object for each language identifier.
Expand Down Expand Up @@ -1323,7 +1352,7 @@ Credential Issuers often want to know what Wallet they are issuing Credentials t

The following mechanisms in concert can be utilized to fulfill those objectives:

**Key attestation** is a mechanism where the device or security element in a device asserts the key management policy to the application creating and using this key. The Android Operating System, for example, provides apps with a certificate including a certificate chain asserting that a particular key is managed, for example, by a hardware security module. The Wallet can provide this data along with the proof of possession in the Credential Request (see (#credential-request) for an example) to allow the Credential Issuer to validate the key management policy. This requires the Credential Issuer to rely on the trust anchor of the certificate chain and the respective key management policy. Another variant of this concept is the use of a Qualified Electronic Signature as defined by the eIDAS regulation [@eIDAS]. This signature will not reveal the properties of the associated private key to the Credential Issuer. However, as one example, due to the regulatory regime of eIDAS, the Credential Issuer can deduce that the signing service manages the private keys according to this regime and fulfills very high security requirements. As another example, FIDO2 allows RPs to obtain an attestation along with the public key from a FIDO authenticator. That implicitly asserts the key management policy, since the assertion is bound to a certain authenticator model and its key management capabilities.
**Key attestation** is a mechanism where the key storage component or Wallet Provider asserts the keys and their security policy. The Wallet can provide this data in the Credential Request to allow the Credential Issuer to validate the key management policy. This requires the Credential Issuer to rely on the trust anchor of the key attestation and the respective key management policy. While some existing platforms have key attestation formats, this specification introduces a common key attestation format that may be used by Credential Issuers for improved interoperability, see [](#keyattestation).

**App Attestation**: Key attestation, however, does not establish trust in the application storing the Credential and producing presentation of that Credential. App attestation, as provided by mobile operating systems, e.g., iOS's DeviceCheck or Android's SafetyNet, allows a server system to ensure it is communicating to a legitimate instance of its genuine app. Those mechanisms can be utilized to validate the internal integrity of the Wallet (as a whole).

Expand Down Expand Up @@ -2166,6 +2195,98 @@ The following is a non-normative example of a Credential Response containing a C

<{{examples/credential_response_sd_jwt_vc.txt}}

# Key Attestations {#keyattestation}

A key attestation defined by this specification is an interoperable, verifiable statement that provides evidence of authenticity and security properties of a key and its storage component to the Credential Issuer. Keys can be stored in various key storage components, which differ in their ability to protect the private key against extraction and duplication, as well as in the methods used for End-User authentication to unlock key operations. These key storage components may be software-based or hardware-based, and can be located on the same device as the Wallet, on external security tokens, or on remote services that enable cryptographic key operations. Key attestations are issued by the Wallet's key storage component itself or by the Wallet Provider. When the Wallet Provider creates the key attestation, it needs to verify the authenticity of the claims it is making about the keys (e.g., by using the platform-specific key attestations).

A Wallet MAY provide key attestations to inform the Credential Issuer about the properties of the provided cryptographic public keys, e.g. for proof types sent in the Credential Request. Credential Issuers may want to evaluate these key attestations to determine whether the keys meet their own security requirements, based on the trust framework in use, regulatory requirements, laws, or internal design decisions. A Credential Issuer SHOULD communicate this requirement to evaluate key attestations through its metadata or using some sort of out-of-band mechanism.
Copy link
Contributor

@nemqe nemqe Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the description of metadata here: https://github.com/openid/OpenID4VCI/pull/389/files#diff-1f424614b35a9899813079f1b1f6218631a2aedd993368ccb89bb81a9eda0289R1308 says

If the Credential Issuer does not expect a key attestation, this object is absent.

Is this sentence here valid

A Credential Issuer SHOULD communicate this requirement to evaluate key attestations through its metadata or using some sort of out-of-band mechanism.

It reads to me that a Credential Issuer can decide to require attestations but not put it in the metadata, but maybe that is the goal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean SHOULD -> MAY ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Justto clarify key attestations are completly optional, but if an Issuer wants them, the typical way in OAuth is to include the needs in the metadata, therefore we added such entries to the Credential Issuer metadata

Copy link
Contributor

@nemqe nemqe Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean SHOULD -> MAY ?

I am not qualified to have this conversations. :) I will try to explain In layman's terms the way I read this

The issuer medatada section says:

If the Credential Issuer does not expect a key attestation, this object is absent.

So my expectation here would be that if I read the metadata, don't find this object, i don't send an attestation as it is not required/expected -- but I think my expectation would be wrong because there is this sentence:

A Credential Issuer SHOULD communicate this requirement to evaluate key attestations through its metadata or using some sort of out-of-band mechanism.

This one reads, for me at least, like "Issuer may choose to require the attestation but the exact way this requirement is communicated is not enforced" i.e. if I go to metadata and see that there is no key_attestations_required it could just mean that this expectation/requirement is defined elsewhere (other metadata, or using the mentioned out-of-band mechanisms like policy or interop profile).

I would potentially just remove the sentence I mentioned above from the issuer metadata section and add a link to the attestation section where one can read that this object can be used to advertise attestation requirement but that the usage of this filed is not mandated for such a purpose and that one needs to consult the issuer's/ecosystem's documentation on whether the wallet must include it or not. Or maybe even not add a link.


paulbastian marked this conversation as resolved.
Show resolved Hide resolved
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
Since key attestations may be used for different Credential Issuers from different trust frameworks and varying in their requirements, it is necessary to use a common approach to facilitate interoperability. Therefore, key attestations SHOULD use a common format, allowing Credential Issuers to develop consistent evaluation processes, reducing complexity and potential errors. Common formats make it easy for Credential Issuers to demonstrate compliance with regulatory requirements across different jurisdictions and facilitate the development of shared best practices and security benchmarks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should OID4VCI also say something about how these key attestations might relate to encryption? We had the discussion in the past that the encryption is not adding a lot on top of TLS because the wallet keys are not trusted necessarily. If the key attestations would also contain keys the wallet provides for encryption, wouldn't this solve this specific problem we had with encryption?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea in general, but I think the keys from the wallet attestation (attestation-based client authenticaiton) may be a better fit, as the wallet attestation generates trust in who the wallet is, key attestation only says this is some valid key from hardware

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wallet attestations are currently defined in HAIP. Probably a separate issue, but would it make sense to create an issue to add a note to the spec to explain how wallet attestation and encryption can relate to each other?


There are two ways to convey key attestations during Credential issuance:
Copy link
Contributor

@awoie awoie Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make sense to allow to convey the key attestations also in the in the Pushed Authorization and/or Token Request, i.e., using OAuth2 attestation-based client authentication? This way, the AS could also make a decision if they want to issue an access/refresh token to the wallet? Or is this mechanism out of scope of OID4VCI while still being possible because an AS can use the OAuth2 client authentication extension mechanism to support this use case anyways?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is out of scope, perhaps adding a note would still make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say in an ideal world, key attestations would be its own draft and could be applied to OpenID4VCI credential request and attestation-based client authentication. If you would want it for access/refresh tokens, it would only require to add attestation claim to the DPoP proof, which I also proposed (see checklist in PR description).

- The Wallet uses the `jwt` proof type in the Credential Request to create a proof of possession of the key and adds the key attestation in the JOSE header as specified in (#jwt-proof-type).
- The Wallet uses the `attestation` proof type in the Credential Request with the key attestation without a proof of possession of the key itself as specified in (#attestation-proof-type).

The latter may avoid unnecessary user interaction during the Credential issuance, as the key itself is not performing a signature operation.
paulbastian marked this conversation as resolved.
Show resolved Hide resolved

## Key Attestation in JWT format {#keyattestation-jwt}

The JWT is signed by the Wallet Provider or the Wallet's key storage component itself and contains the following elements:

* in the JOSE header,
* `alg`: REQUIRED. A digital signature algorithm identifier such as per IANA "JSON Web Signature and Encryption Algorithms" registry [@IANA.JOSE.ALGS]. It MUST NOT be `none` or an identifier for a symmetric algorithm (MAC).
* `typ`: REQUIRED. MUST be `keyattestation+jwt`, which explicitly types the key proof JWT as recommended in Section 3.11 of [@!RFC8725].

The key attestation may use `x5c`, `kid` or `trust_chain` (as defined in (#jwt-proof-type) ) to convey the public key and the associated trust mechanism to sign the key attestation.

* in the JWT body,
* `iat`: REQUIRED (number). Integer for the time at which the key attestation was issued using the syntax defined in [@!RFC7519].
* `exp`: REQUIRED (number). Integer for the time at which the key attestation and the key(s) it is attesting expire, using the syntax defined in [@!RFC7519].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in JWT proof type, we only defined iat, and did not define exp, because we said it is up to the issuer's policy to decide how long to accept the proofs. why do we need exp here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the assurances about a key storage component and its keys usually have an expiration, see recommendations from BSI and NIST

Copy link
Member

@c2bo c2bo Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I would agree this is a bit different: The key attestation might not come from the wallet directly, but a third party (the wallet provider). The wallet provider should be able to signal (via expiration) how long such an expiration should be deemed valid.
I am wondering if there are there cases where we think it should be optional instead of required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to resolve?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it makes sense for pre-generated key attestations in jwt proof type - it can also be a signal when a wallet needs to ask wallet backend to re-generate the key attestation. but i think it makes less sense in key attestations in attestation proof type, that are generated fresh, with issuer-provided nonce.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking with security-by-design I would like to let everything expire

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it OPTIONAL?

There is a status claim defined below so I guess the attestation generated by the Wallet Provider could be revocable if it is meant to be long lived or it could use the exp otherwise to limit the lifetime of the attestation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the discussion, would this be acceptable for everyone?

Suggested change
* `exp`: REQUIRED (number). Integer for the time at which the key attestation and the key(s) it is attesting expire, using the syntax defined in [@!RFC7519].
* `exp`: OPTIONAL (number). Integer for the time at which the key attestation and the key(s) it is attesting expire, using the syntax defined in [@!RFC7519]. MUST be present if the attestation is used with the attestation proof type.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!

* `attested_keys` : REQUIRED. Array of attested keys from the same key storage component using the syntax of JWK as defined in [@!RFC7517].
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering it this could be an JWKS (https://www.rfc-editor.org/rfc/rfc7517.html#section-5) instead of directly an array if JWK. Having an object here is an extra indirection however it is a standard representation and provides "extra space" to add more common properties to this set of keys.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using JWKS would also allow a single top-level claims, with the extra properties being defined inside the JWKS (which allows for extensibility):

"attested_keys" {
    "keys": [{"...":"..."}, {"...":"..."}],
    "key_type": "strong_box",
    "user_authentication": ["system_biometry", "system_pin"]
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking a bit more, a better design could be

"attested_keys": {
    "keys": [{"...":"..."}, {"...":"..."}],
    "attestation": {
        "key_type": "strong_box",
        "user_authentication": ["system_biometry", "system_pin"],
        "a_future_extension": "with some value"
    }
}
  • A single JWT claim registration - attested_keys
  • A single JSON Web Key Set Parameter registeration - attestation.
  • An extensible object with attestation information, including key_type, user_authentication and other future properties.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this model also allows for key derivation scenarios (e.g. Hierarchical
Deterministic Keys), where instead of explicitly listing all the keys, the attestation contains some seed parameters for the key generation?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the proposal. JWKS make sense

Copy link
Contributor Author

@paulbastian paulbastian Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer nesting and attested_keys is a JWKS, I'd prefer:

"attested_keys": {
    "keys": [{"...":"..."}, {"...":"..."}],
    "key_type": "strong_box",
    "user_authentication": ["system_biometry", "system_pin"],
    "a_future_extension": "with some value"
}

JWKS Parameters is an existing IANA Registry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning is that this spec would contribute with a single parameter to the JWKS Parameters IANA register (e.g. attestation), which would be an object. The schema of this object and its extensibility would be own by this spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brian expresses concerns about registering these parameters to IANA

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, if attested_keys is defined to be a JWKS object as defined in RFC 7517, then it is probably necessary to register included parameters with IANA. Currently, there is only one parameter registered in the IANA JWKS registry which is keys. To avoid name clashes, these additional ones have to be registered there as well.

On the other hand, if we would just not define attested_keys as a JWKS but instead fully define it which would also require defining keys, then no IANA registration is needed.

* `key_storage_type` : OPTIONAL. Case sensitive string that asserts the key storage component of the keys attested in the `attested_keys` parameter. This specification defines initial values in (#keyattestation-keytypes).
* `user_authentication` : OPTIONAL. Array of case sensitive strings that assert the authentication methods allowed to access the private keys from the `attested_keys` parameter. This specification defines initial values in (#keyattestation-auth).
Copy link
Contributor

@awoie awoie Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the methods defined in user_authentication evaluated as OR or AND? If they are OR, then how would you encode MFA?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was meant as logical OR, does this text fit better or do you have better words?

Suggested change
* `user_authentication` : OPTIONAL. Array of case sensitive strings that assert the authentication methods allowed to access the private keys from the `attested_keys` parameter. This specification defines initial values in (#keyattestation-auth).
* `user_authentication` : OPTIONAL. Array of case sensitive strings that assert the authentication methods allowed to access the private keys from the `attested_keys` parameter. The values given it this array are interpreted as a logical OR. This specification defines initial values in (#keyattestation-auth).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to clarify: the key given from key_storage_type forms the possession factor. So whatever is in user_authentication already creates MFA. If you want 3FA, then we would need to create a user_authentication value like pin_and_biometry

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this would meet NIST 2FA requirements for all listed cases since both factors have to be independent, i.e., especially not sure if the key is stored by the app and the device biometrics to unlock the same app are used would meet the 2FA requirement.

However, I'm fine with the suggested text to resolve this issue.

* `apr` : OPTIONAL. Array of case sensitive strings that assert attested resistance to specified attack potentials for the given keys. The string values contain URNs that identify the given attack potentials.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this claim name coming from..? and what are the potential values of the URNs..?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISO/IEC 18045 is the most common way, we could have the initial values from the spec

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is not a freely available standard, and i would expect a push back relying on it? but if that is a starting point, pointing to it as a place where to find URNs would be kind.

but what does this claim name even stand for..?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attack potential resistance - from my understanding it's basically a more refined way to define what level of security a system can achieve and what attack vectors it cannot prevent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked experts to provide initial values for this, hope to add some initial values or to improve the text within the next days.

* `nonce`: OPTIONAL. String that represents a nonce provided by the Issuer to prove that a key attestation was freshly generated.
* `status`: OPTIONAL. JSON Object representing the supported revocation check mechanisms, such as the one defined in [@!I-D.ietf-oauth-status-list]

paulbastian marked this conversation as resolved.
Show resolved Hide resolved
The Credential Issuer MUST validate that the JWT used as a proof is actually signed by a key identified in the JOSE Header.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this object also used for proof type "attestation"? If so, this statement should be conditional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are correct. @c2bo did you add this text?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from from your initial commit, but it seems I forgot to change it when introducing the second proof type. We should move this into the jwt proof type text imho.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The Credential Issuer MUST validate that the JWT used as a proof is actually signed by a key identified in the JOSE Header.
If used with the `jwt` proof type, the Credential Issuer MUST validate that the JWT used as a proof is signed by a key contained in the attestation in the JOSE Header.


This is an example of a Key Attestation:

```json
{
"typ": "keyattestation+jwt",
"alg": "ES256",
"kid": "1"
Copy link
Contributor

@nemqe nemqe Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stupid comment, but this kid is a bit confusing for me here in this form, is this referring to a particular key from the attestation or is it just a random value for the sake of the example?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This jwt would be signed by the Wallet Backend or the key storage directly - it cannot be referring to a key from the attestation. But it might make sense to change it to x5c for the example to avoid confusion?

Suggested change
"kid": "1"
"x5c": ["MIIDQjCCA..."]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would just point out this thing if it makes sense.

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

Object providing a single proof of possession of the cryptographic key material to which the issued Credential instance will be bound to...

Not sure if this will be in conflict because now credentials are not then bound to the key doing the proof or possession

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! We probably need to adapt those lines describing proofs and proof a bit. We still get a proof that the wallet is in possession of the key(s), it just doesn't have to be a proof of possession.

}
.
{
"iss": "<identifier of the issuer of this key attestation>",
"iat": 1516247022,
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
"exp": 1541493724,
"key_storage_type": "strong_box",
"user_authentication": [ "system_pin", "system_biometry" ],
"apr" : [ "https://trust-list.eu/apr/high" ],
"attested_keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
"y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
}
]
}
```

## Key Types {#keyattestation-keytypes}

This specification defines the following values for `key_storage_type`:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without any further information or references, I believe it is almost impossible for a reader to know what Trusted Execution Environment or Secure Element mean. If they are supposed to refer to Android and iOS concepts, should we include explicit references or description.

If the OpenID4VCI spec defines these identifiers then it also need to define its meaning in a usable way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, references are needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best reference I was able to find was section 3.3 of ISO 27071 (https://www.iso.org/obp/ui/en/#iso:std:iso-iec:27071:ed-1:v1:en) for the general descriptions and then reference ios (secure enclace) and android (strong box) directly?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an additional question, what is meant with secure_element? Is that an abstraction to unify the Android and iOS concepts (secure_enclave and strong_box)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say both secure enclave and strong box are subtypes of a secure element.
In general I would say, a secure element is a security chip/component that provides a secure platform that is capable of securely running applications and storing its confidential data (keys etc).

Copy link
Contributor Author

@paulbastian paulbastian Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trusted Execution Environments are isolated secured processing areas on a common purpose main processor running its own operating system.
Secure Elements usually refers to Common Criteria certified chips that use ISO7816 or ISO14443 from the smartcard industry.

I agree that we would use some references and further explanations for the key types

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there were specs for TEE in their own standards body, right?

Copy link
Contributor

@awoie awoie Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a rabbit hole but to be even more specific, Secure Elements themselves can also comply to different Common Criteria protection profiles which means they can have different characteristics, i.e., not all of them are equally secure, and some of them don't even comply to any since they didn't perform certification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awoie that's correct. That's why the apr claim is actually the most interesting one, but for some this is hard to measure and some people will not have the security background to know what it actually means, that's why I put key_storage_type and user_authentication as a more approachable/easy way to describe the key storage component

* `software`: It MUST be used when the Wallet uses software-based key management.
* `tee`: It MUST be used when the Wallet uses the Trusted Execution Environment for key management.
* `secure_enclave`: It MUST be used when the Wallet uses the Secure Enclave for key management.
* `strong_box`: It MUST be used when the Wallet uses the Strongbox for key management.
* `secure_element`: It MUST be used when the Wallet uses a Secure Element for key management.
paulbastian marked this conversation as resolved.
Show resolved Hide resolved
* `external`: It MUST be used when the Wallet uses a local external hardware token for key management.
* `hsm`: It MUST be used when the Wallet uses Hardware Security Module (HSM) for key management.
* `remote_hsm`: It MUST be used when the Wallet uses Hardware Security Module (HSM) that is not directly connected to the Wallet for key management.

paulbastian marked this conversation as resolved.
Show resolved Hide resolved
Specifications that extend this list MUST choose collision-resistant values.

## User Authentication Types {#keyattestation-auth}

This specification defines the following values for `user_authentication`:

* `system_biometry`: It MUST be used when the key usage is authorized by the key storage component itself or the associated operating system using a biometric factor, such as the one provided by mobile devices.
* `system_pin`: It MUST be used when the key usage is authorized by the key storage component itself or the associated operating system using personal identification number (PIN).
* `remote_biometry`: It MUST be used when the key usage is authorized by a remote system using a biometric factor.
* `remote_pin`: It MUST be used when the key usage is authorized by a remote system using a PIN.
Specifications that extend this list MUST choose collision-resistant values.

## Attack Potential Resistance {#keyattestation-apr}

This specification does not define any specific vaues for `apr`. Ecosystems may define their own values, any URN is a valid value. It is RECOMMENDED that the value is a URL that gives further information about the attack potential resistance and possible relations to level of assurances.

# IANA Considerations

## Sub-Namespace Registration
Expand Down Expand Up @@ -2314,6 +2435,7 @@ The technology described in this specification was made available from contribut

-14

* add key attestation as additional information in a proof of possesion and new proof type
* removes CWT proof type
* removes the Batch Credential Endpoint
* clarify that authorization_details can be present in the Token Request for Pre-Authorized Code Flow when multiple Credential Configurations are present in the Credential Offer
Expand Down