Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions doc/crypto/api.db/psa/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ typedef struct psa_custom_key_parameters_t {
#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002)
#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200)
#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00004000)
#define PSA_KEY_USAGE_DERIVE_PUBLIC ((psa_key_usage_t)0x00000080)
#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100)
#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001)
#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00001000)
Expand Down Expand Up @@ -464,6 +465,9 @@ psa_status_t psa_attach_key(const psa_key_attributes_t * attributes,
const uint8_t * label,
size_t label_length,
psa_key_id_t * key);
psa_status_t psa_check_key_usage(psa_key_id_t key,
psa_algorithm_t alg,
psa_key_usage_t usage);
psa_status_t psa_cipher_abort(psa_cipher_operation_t * operation);
psa_status_t psa_cipher_decrypt(psa_key_id_t key,
psa_algorithm_t alg,
Expand Down
136 changes: 120 additions & 16 deletions doc/crypto/api/keys/policy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,17 @@ When a key is used in a cryptographic operation, the application must supply the
Key usage flags
---------------

The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. Four kinds of usage flag can be specified:
The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. There are two kinds of usage flag:

* The extractable flag `PSA_KEY_USAGE_EXPORT` determines whether the key material can be extracted from the cryptoprocessor, or copied outside of its current security boundary.
* The copyable flag `PSA_KEY_USAGE_COPY` determines whether the key material can be copied into a new key, which can have a different lifetime or a more restrictive policy.
* The cacheable flag `PSA_KEY_USAGE_CACHE` determines whether the implementation is permitted to retain non-essential copies of the key material in RAM. This policy only applies to persistent keys. See also :secref:`key-material`.
* The following usage flags determine whether the corresponding operations are permitted with the key:
1. Key-management usage flags.

- The extractable flag `PSA_KEY_USAGE_EXPORT` determines whether the key material can be extracted from the cryptoprocessor, or copied outside of its current security boundary.
- The copyable flag `PSA_KEY_USAGE_COPY` determines whether the key material can be copied into a new key, which can have a different lifetime or a more restrictive policy.
- The cacheable flag `PSA_KEY_USAGE_CACHE` determines whether the implementation is permitted to retain non-essential copies of the key material in RAM. This policy only applies to persistent keys. See also :secref:`key-material`.

2. Cryptographic-operation usage flags.

The following usage flags determine whether the corresponding cryptographic operations are permitted with the key:

- `PSA_KEY_USAGE_ENCRYPT`
- `PSA_KEY_USAGE_DECRYPT`
Expand All @@ -97,6 +102,8 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
- `PSA_KEY_USAGE_DERIVE`
- `PSA_KEY_USAGE_VERIFY_DERIVATION`

The flag `PSA_KEY_USAGE_DERIVE_PUBLIC` is used in the function `psa_check_key_usage()` to query if a key can be used for the public role in the specified algorithm.

.. typedef:: uint32_t psa_key_usage_t

.. summary::
Expand All @@ -108,7 +115,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to export the key.

This flag permits a key to be moved outside of the security boundary of its current storage location. In particular:
This key-management usage flag permits a key to be moved outside of the security boundary of its current storage location. In particular:

* This flag is required to export a key from the cryptoprocessor using `psa_export_key()`. A public key or the public part of a key pair can always be exported regardless of the value of this permission flag.

Expand All @@ -122,7 +129,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to copy the key.

This flag is required to make a copy of a key using `psa_copy_key()`.
This key-management usage flag is required to make a copy of a key using `psa_copy_key()`.

For a key lifetime that corresponds to a secure element location that enforces the non-exportability of keys, copying a key outside the secure element also requires the usage flag `PSA_KEY_USAGE_EXPORT`. Copying the key within the secure element is permitted with just `PSA_KEY_USAGE_COPY`, if the secure element supports it. For keys with the lifetime `PSA_KEY_LIFETIME_VOLATILE` or `PSA_KEY_LIFETIME_PERSISTENT`, the usage flag `PSA_KEY_USAGE_COPY` is sufficient to permit the copy.

Expand All @@ -132,7 +139,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission for the implementation to cache the key.

This flag permits the implementation to make additional copies of the key material that are not in storage and not for the purpose of an ongoing operation. Applications can use it as a hint for the cryptoprocessor, to keep a copy of the key around for repeated access.
This key-management usage flag permits the implementation to make additional copies of the key material that are not in storage and not for the purpose of an ongoing operation. Applications can use it as a hint for the cryptoprocessor, to keep a copy of the key around for repeated access.

An application can request that cached key material is removed from memory by calling `psa_purge_key()`.

Expand All @@ -153,7 +160,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to encrypt a message, or perform key encapsulation, with the key.

This flag is required to use the key in a symmetric encryption operation, in an AEAD encryption-and-authentication operation, in an asymmetric encryption operation, or in a key-encapsulation operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key in a symmetric encryption operation, in an AEAD encryption-and-authentication operation, in an asymmetric encryption operation, or in a key-encapsulation operation. The flag must be present on keys used with the following APIs:

* `psa_cipher_encrypt()`
* `psa_cipher_encrypt_setup()`
Expand All @@ -170,7 +177,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to decrypt a message, or perform key decapsulation, with the key.

This flag is required to use the key in a symmetric decryption operation, in an AEAD decryption-and-verification operation, in an asymmetric decryption operation, or in a key-decapsulation operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key in a symmetric decryption operation, in an AEAD decryption-and-verification operation, in an asymmetric decryption operation, or in a key-decapsulation operation. The flag must be present on keys used with the following APIs:

* `psa_cipher_decrypt()`
* `psa_cipher_decrypt_setup()`
Expand All @@ -187,7 +194,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to sign a message with the key.

This flag is required to use the key in a MAC calculation operation, or in an asymmetric message signature operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key in a MAC calculation operation, or in an asymmetric message signature operation. The flag must be present on keys used with the following APIs:

* `psa_mac_compute()`
* `psa_mac_sign_setup()`
Expand All @@ -201,7 +208,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to verify a message signature with the key.

This flag is required to use the key in a MAC verification operation, or in an asymmetric message signature verification operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key in a MAC verification operation, or in an asymmetric message signature verification operation. The flag must be present on keys used with the following APIs:

* `psa_mac_verify()`
* `psa_mac_verify_setup()`
Expand All @@ -215,7 +222,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to sign a message hash with the key.

This flag is required to use the key to sign a pre-computed message hash in an asymmetric signature operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key to sign a pre-computed message hash in an asymmetric signature operation. The flag must be present on keys used with the following APIs:

* `psa_sign_hash()`

Expand All @@ -229,7 +236,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to verify a message hash with the key.

This flag is required to use the key to verify a pre-computed message hash in an asymmetric signature verification operation. The flag must be present on keys used with the following APIs:
This cryptographic-operation usage flag is required to use the key to verify a pre-computed message hash in an asymmetric signature verification operation. The flag must be present on keys used with the following APIs:

* `psa_verify_hash()`

Expand All @@ -243,7 +250,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. summary::
Permission to derive other keys or produce a password hash from this key.

This flag is required to use the key for derivation in a key-derivation operation, or in a key-agreement operation.
This cryptographic-operation usage flag is required to use the key for derivation in a key-derivation operation, or in a key-agreement operation.

This flag must be present on keys used with the following APIs:

Expand All @@ -261,12 +268,32 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.

.. versionadded:: 1.1

This flag is required to use the key for verification in a key-derivation operation.
This cryptographic-operation usage flag is required to use the key for verification in a key-derivation operation.

This flag must be present on keys used with `psa_key_derivation_verify_key()`.

If this flag is present on all keys used in calls to `psa_key_derivation_input_key()` for a key-derivation operation, then it permits calling `psa_key_derivation_verify_bytes()` or `psa_key_derivation_verify_key()` at the end of the operation.

.. macro:: PSA_KEY_USAGE_DERIVE_PUBLIC
:definition: ((psa_key_usage_t)0x00000080)

.. summary::
Used in the `psa_check_key_usage()` function to determine if the key can be used in the public key role in a key-agreement or a PAKE operation.

.. versionadded:: 1.4

This cryptographic-operation usage flag is only used with the `psa_check_key_usage()` function.
This flag is not currently checked when performing any cryptographic operation.

For example, calling `psa_check_key_usage()` with `PSA_KEY_USAGE_DERIVE_PUBLIC` and with:

* `PSA_ALG_ECDH` checks that the key can be used as the public share in the ECDH key agreement.
There are no checks on permissions as the key share is provided in a buffer.
* `PSA_ALG_SPAKE2P_HMAC` will check that the key can be used in the Verifier role in the SPAKE2+ algorithm.
The key must have the `PSA_KEY_USAGE_DERIVE` permission.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we change that to allow either PSA_KEY_USAGE_DERIVE or PSA_KEY_USAGE_DERIVE_PUBLIC?

The situation is actually somewhat similar to PSA_KEY_USAGE_SIGN_MESSAGE vs PSA_KEY_USAGE_SIGN_HASH, in that we had keys originally created with only the SIGN_HASH permission and we wanted to allow them for an operation that is naturally controlled by SIGN_MESSAGE. What we did then was to say that any key created with the SIGN_MESSAGE flag also gains the SIGN_HASH flag (reported if you query the key's usage). So maybe we should do the same here, namely say that any key created with PSA_KEY_USAGE_DERIVE also gains PSA_KEY_USAGE_DERIVE_PUBLIC (if the crypto core complies with spec 1.4), in addition to changing the requirement in psa_pake_setup to require DERIVE_PUBLIC when doing an operation in the verifier role?

Copy link
Contributor

@athoelke athoelke Sep 12, 2025

Choose a reason for hiding this comment

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

It was the other way around: setting PSA_KEY_USAGE_SIGN_HASH causes PSA_KEY_USAGE_SIGN_MESSAGE to also be set for the key. But the pattern fits in this case as well.

As well as source code compatibility, we probably ought to consider an existing key store in which a SPAKE2+ verifier (public) key only has DERIVE usage, and for which the policy is not updatable. In this case, we would want the updated implementation to accept a SPAKE2+ public key with DERIVE usage. Perhaps the wording should be that keys created with DERIVE usage, implicitly also have DERIVE_PUBLIC usage - and it is undefined whether that happens when the key is stored, or when the usage flags are inspected?

For newly created/derived keys (if we introduce this change), then the ('connected registration' flow in Figure 4 of SPAKE2+ registration) would set DERIVE_PUBLIC on the key imported into the Verifier key store, instead of DERIVE.

If the verifier key is not transferred from the Prover during the registration phase, and both roles start from the shared password ('independent registration' in Figure 4 of SPAKE2+ registration) - then the Verifier will derive the SPAKE2+ key pair from the password, and just provide the key-pair to the PAKE operation for the Verifier role. In this case the verifier could just set DERIVE_PUBLIC usage on the key-pair, which restricts it to only be valid in the Verifier role (and makes the Prover part of the key-pair unusable in that key object).

In both cases, DERIVE usage should be permitted, for source code compatibility for applications written against the current spec - this utilises the 'implicit DERIVE_PUBLIC' rule described above.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that adopting PSA_KEY_USAGE_DERIVE_PUBLIC as a 1st-class policy flag, as described here, is not necessary for this particular PR that introduces the flag to enable the desired psa_check_key_usage() behavior.

I am going to split this idea, and its discussion, into a separate Issue, that can be pursued as a follow-up to this PR.

* `PSA_ALG_HKDF` is invalid, as there is no such role in single-key derivation algorithms.


.. function:: psa_set_key_usage_flags

.. summary::
Expand Down Expand Up @@ -302,3 +329,80 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`.
.. admonition:: Implementation note

This is a simple accessor function that is not required to validate its inputs. It can be efficiently implemented as a ``static inline`` function or a function-like-macro.

.. function:: psa_check_key_usage

.. summary::
Query the capability of a key.

.. versionadded:: 1.4

.. param:: psa_key_id_t key
Identifier of the key to check.
.. param:: psa_algorithm_t alg
An algorithm identifier: a value of type `psa_algorithm_t`.
.. param:: psa_key_usage_t usage
A single ``PSA_KEY_USAGE_xxx`` flag.

.. return:: psa_status_t

.. retval:: PSA_SUCCESS
``key`` can be used for the requested operation on this implementation.
.. retval:: PSA_ERROR_INVALID_ARGUMENT
The following conditions can result in this error:

* ``usage`` is a key-management usage flag and ``alg`` is not `PSA_ALG_NONE`.
* ``usage`` is a cryptographic-operation usage flag and ``alg`` is not a valid, specific algorithm.
A 'specific algorithm' is one that is neither `PSA_ALG_NONE` nor a wildcard algorithm.
* ``usage`` is not a valid role for algorithm ``alg``.
* ``key`` is not compatible with ``alg`` and ``usage``.
.. retval: PSA_ERROR_INVALID_HANDLE:
``key`` is not a valid key identifier.
.. retval: PSA_ERROR_NOT_PERMITTED
``key`` does not permit the requested usage or algorithm.
.. retval:: PSA_ERROR_NOT_SUPPORTED
The following conditions can result in this error:

* The implementation does not support algorithm ``alg``.
* The implementation does not support using ``key`` with the operation associated with ``alg`` and ``usage``.
.. retval:: PSA_ERROR_INSUFFICIENT_MEMORY
.. retval:: PSA_ERROR_COMMUNICATION_FAILURE
.. retval:: PSA_ERROR_CORRUPTION_DETECTED
.. retval:: PSA_ERROR_STORAGE_FAILURE
.. retval:: PSA_ERROR_DATA_CORRUPT
.. retval:: PSA_ERROR_DATA_INVALID
.. retval:: PSA_ERROR_BAD_STATE
The library requires initializing by a call to `psa_crypto_init()`.

This function reports whether the implementation supports the use of a key with the operation associated with a provided algorithm and usage.
This function does not attempt to perform the operation.

If ``usage`` is a key-management usage flag, then:

* ``alg`` must be `PSA_ALG_NONE`.
* ``key`` must exist, and permit the requested usage flag.

If ``usage`` is a cryptographic-operation usage flag, then:

* ``alg`` must be a valid, fully specified algorithm, and not a wildcard.
For example:

- :code:`PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)` is invalid as it is a wildcard algorithm.
- :code:`PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 9)` is invalid as it has an invalid tag-length for GCM.
- :code:`PSA_ALG_SPAKE2P_HMAC(PSA_ALG_SHA_1)` is invalid as SPAKE2+ does have SHA-1 in any cipher-suite.
* ``usage`` must identify a valid role within the algorithm.
For example, if :code:`alg == PSA_ALG_GCM`, the ``usage`` must be either `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT`, as these are the key-usage policy flags for AEAD functions.
* ``key`` must exist, have a type and size that are compatible with the operation associated with ``alg`` and ``usage``, and have the required permission for the algorithm and usage.
For example:

- An Edwards25519 key pair is not compatible with :code:`PSA_ALG_ECDSA(PSA_ALG_SHA_256)`.
- A ``512``-bit RSA key pair is not compatible with :code:`PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)` as the algorithm requires a larger key size.
- A ``512``-bit AES key (double-length key for use in AES-256-XTS) is not compatible with `PSA_ALG_CTR`.

.. note::
For the key pair or public key of a valid type in a key agreement function, this function returns :code:`PSA_SUCCESS` for the usage `PSA_KEY_USAGE_DERIVE_PUBLIC`, regardless of the key's policy.
This is because the corresponding API functions take a key buffer as input, not a key object, and the key data can extracted by calling `psa_export_public_key()`, which does not require any usage flag.

.. admonition:: Implementation note

The intended behavior of this function is to include any check that can be made using the accessible key attributes, but without requiring logic or arithmetic using the key material.
1 change: 1 addition & 0 deletions doc/crypto/appendix/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Changes to the API
~~~~~~~~~~~~~~~~~~

* Added `psa_attach_key()` to register existing key material as a volatile key within the implementation.
* Added `psa_check_key_usage()` to query a key's capabilities.

Clarifications and fixes
~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down