Skip to content

API to query a key's capabilities #279

@gilles-peskine-arm

Description

@gilles-peskine-arm

User stories

As a developer implementing a protocol involving cryptography (e.g. TLS),
I want to query the capabilities of a PSA key object,
so that I can decide which protocol options (e.g. cipher suites or key exchange types) the key is compatible with.

As a developer implementing a key management interface,
I want to query the capabilities of a PSA key object,
so that I can enable the correct operations on it.

Requirement

In principle, both user stories can be implemented on top of psa_get_key_attributes: just analyze the key type and policy. However, this is difficult for several reasons:

  • I need to have logic covering all the cryptographic mechanisms that I support. In the protocol user story, that's doable, but duplicates code that already exists in the PSA crypto implementation to determine whether an operation is possible. In the key management user story, I would have to reimplement everything.
  • If the implementation supports vendor-specific mechanisms, they should be included. Again, that's necessary in the key management user story, and less burdensome in the protocol user story.
  • If the implementation has additional policy restrictions, they should apply. For example, if an implementation allows small RSA keys to be used to verify (presumably old) signatures but not encrypt new material, that should be reflected in this capability interface.
  • If the implementation has additional policies (such as Mbed TLS's enrollment algorithm, which allows a key to have a second permitted algorithm), this should be reflected.

Mbed TLS

In Mbed TLS ≥3.2, this API exists for key pair objects under the name mbedtls_pk_can_do_ext().

int mbedtls_pk_can_do_ext(
    const mbedtls_pk_context *ctx,
    psa_algorithm_t alg,
    psa_key_usage_t usage);
  • ctx is a proprietary representation of a key in memory. The PSA analog is a key identifier.
  • alg is a PSA algorithm PSA_ALG_xxx.
  • usage is a single PSA_KEY_USAGE_xxx flag.
  • The return value is a boolean.

For example mbedtls_pk_can_do_ext(ctx, PSA_ALG_RSA_PSS, PSA_KEY_USAGE_SIGN_HASH(PSA_ALG_SHA_256)) checks whether ctx is an RSA key which is allowed by policy to perform a PSS signature using SHA-256. It is always false for an ECC key regardless of policy.

In the next version, we want to extend this function to also support public keys. So for example mbedtls_pk_can_do_ext(ctx, PSA_ALG_RSA_PSS, PSA_KEY_USAGE_SIGN_HASH(PSA_ALG_SHA_256)) can only be true for an RSA key pair, whereas mbedtls_pk_can_do_ext(ctx, PSA_ALG_RSA_PSS, PSA_KEY_USAGE_VERIFY_HASH(PSA_ALG_SHA_256)) can also be true for an RSA public key.

Proposed interface

I think the design of the Mbed TLS function has proved itself, so I just propose to tweak it to fit PSA. Name TBD.

psa_status_t psa_check_key_usage(
    psa_key_id_t key,
    psa_algorithm_t alg,
    psa_key_usage_t usage);
  • key: a PSA key identifier.
  • alg: an algorithm. (Not a wildcard algorithm policy — I'm not sure whether this should mean “can do all of” or “can do at least one of”, and I propose to just reject wildcards for now.)
  • usage: a single PSA_KEY_USAGE_xxx flag. Only flags corresponding to an operation that uses an algorithm are meaningful here; flags like COPY and EXPORT are not. (Those are simple booleans that you can query from the attributes, unlike operation capabilities which require checks on the key type and algorithm as well.)
  • Return values:
    • PSA_SUCCESS — yes, the key can do this.
    • PSA_ERROR_INVALID_ARGUMENT or PSA_ERROR_NOT_SUPPORTED or PSA_ERROR_NOT_PERMITTED — no, the key can't do this.
    • PSA_ERROR_INVALID_HANDLE — the key doesn't exist.

A flag for the public side of a key agreement

How do I ask whether a key is suitable for the public side of a key agreement? E.g. how do I formulate

psa_check_key_usage(key, PSA_ALG_ECDH, ???)

so that it's true for an ECC public key? Note that this cannot be PSA_KEY_USAGE_DERIVE, since

psa_check_key_usage(key, PSA_ALG_ECDH, PSA_KEY_USAGE_DERIVE)

requires a key pair.

This hasn't come up in key policies because psa_key_agreement() and its variants take the representation of the public key as an argument, rather than a key object. (The API is optimized for ephemeral Diffie-Hellman over the much rarer static Diffie-Hellman.)

Tentative proposal: a new usage flag PSA_KEY_USAGE_DERIVE_PUBLIC. What would it mean in key policies?

Metadata

Metadata

Assignees

No one assigned

    Labels

    API designRelated the design of the APICrypto APIIssue or PR related to the Cryptography APIenhancementNew feature or request

    Projects

    Status

    In Progress

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions