.. _key-attributes:

Key attributes
==============

Attribute types
---------------

.. typedef:: uint32_t psa_key_lifetime_t

    .. summary::
        Encoding of key lifetimes.

    The lifetime of a key indicates where it is stored and which application and system actions will create and destroy it.

    Keys with the lifetime `PSA_KEY_LIFETIME_VOLATILE` are automatically destroyed when the application terminates or on a power reset.

    Keys with a lifetime other than `PSA_KEY_LIFETIME_VOLATILE` are said to be *persistent*. Persistent keys are preserved if the application or the system restarts. Persistent keys have a key identifier of type `psa_key_id_t`.

    See :title:`key-locations` for a list of defined key lifetimes.

.. typedef:: uint32_t psa_key_id_t

    .. summary::
        Key identifier.

    A key identifiers can be a permanent name for a persistent key, or a transient reference to volatile key. The range of identifier values is divided as follows:

    :code:`PSA_KEY_ID_NULL`
        Reserved as an invalid key identifier.
    :code:`PSA_KEY_ID_USER_MIN - PSA_KEY_ID_USER_MAX`
        Applications can freely choose persistent key identifiers in this range.
    :code:`PSA_KEY_ID_VENDOR_MIN - PSA_KEY_ID_VENDOR_MAX`
        Implementations can define additional persistent key identifiers in this
        range, and allocate key identifiers for volatile keys from this range.

    Key identifiers outside these ranges are reserved for future use.

    See also :title:`key-ids`.

.. typedef:: uint16_t psa_key_type_t

    .. summary::
        Encoding of a key type.

    This is a structured bitfield that identifies the category and type of key. The range of key type values is divided as follows:

    :code:`PSA_KEY_TYPE_NONE == 0`
        Reserved as an invalid key type.
    :code:`0x0001 - 0x7fff`
        Specification-defined key types.
        Key types defined by this standard always have bit 15 clear.
        Unallocated key type values in this range are reserved for future use.
    :code:`0x8000 - 0xffff`
        Implementation-defined key types.
        Implementations that define additional key types must use an encoding with bit 15 set.
        The related support macros will be easier to write if these key encodings also respect the bitwise structure used by standard encodings.

    See :title:`key-types` for a complete list of key types.

.. typedef:: uint32_t psa_key_usage_t

    .. summary::
        Encoding of permitted usage on a key.

    See :title:`key-usage` for a full list of key usage policies.

.. typedef:: uint32_t psa_algorithm_t

    .. summary::
        Encoding of a cryptographic algorithm.

    This is a structured bitfield that identifies the category and type of algorithm. The range of algorithm identifier values is divided as follows:

    :code:`0x00000000`
        Reserved as an invalid algorithm identifier.
    :code:`0x00000001 - 0x7fffffff`
        Specification-defined algorithm identifiers.
        Algorithm identifiers defined by this standard always have bit 31 clear.
        Unallocated algorithm identifier values in this range are reserved for future use.
    :code:`0x80000000 - 0xffffffff`
        Implementation-defined algorithm identifiers.
        Implementations that define additional algorithms must use an encoding with bit 31 set.
        The related support macros will be easier to write if these algorithm identifier encodings also respect the bitwise structure used by standard encodings.

    For algorithms that can be applied to multiple key types, this identifier does not encode the key type. For example, for symmetric ciphers based on a block cipher, `psa_algorithm_t` encodes the block cipher mode and the padding mode while the block cipher itself is encoded via `psa_key_type_t`.

    See :title:`algorithms` for a full list of algorithm identifiers.

Managing attributes
-------------------

.. typedef:: /* implementation-defined type */ psa_key_attributes_t

    .. summary::
        The type of an object containing key attributes.

    This is the object that represents the metadata of a key object. Metadata that can be stored in attributes includes:

    * The location of the key in storage, indicated by its key identifier and its lifetime.
    * The key's policy, comprising usage flags and a specification of the permitted algorithm(s).
    * Information about the key itself: the key type and its size.
    * Implementations can define additional attributes.

    The actual key material is not considered an attribute of a key. Key attributes do not contain information that is generally considered highly confidential.

    .. note::
        Implementations are recommended to define the attribute object as a simple data structure, with fields corresponding to the individual key attributes. In such an implementation, each function ``psa_set_key_xxx()`` sets a field and the corresponding function ``psa_get_key_xxx()`` retrieves the value of the field.

        An implementations can report attribute values that are equivalent to the original one, but have a different encoding. For example, an implementation can use a more compact representation for types where many bit-patterns are invalid or not supported, and store all values that it does not support as a special marker value. In such an implementation, after setting an invalid value, the corresponding get function returns an invalid value which might not be the one that was originally stored.

    This is an implementation-defined type. Applications that make assumptions about the content of this object will result in in implementation-specific behavior, and are non-portable.

    An attribute object can contain references to auxiliary resources, for example pointers to allocated memory or indirect references to pre-calculated values. In order to free such resources, the application must call `psa_reset_key_attributes()`. As an exception, calling `psa_reset_key_attributes()` on an attribute object is optional if the object has only been modified by the following functions since it was initialized or last reset with `psa_reset_key_attributes()`:

    * `psa_set_key_id()`
    * `psa_set_key_lifetime()`
    * `psa_set_key_type()`
    * `psa_set_key_bits()`
    * `psa_set_key_usage_flags()`
    * `psa_set_key_algorithm()`

    Before calling any function on a key attribute object, the application must initialize it by any of the following means:

    * Set the object to all-bits-zero, for example:

      .. autocode::
          psa_key_attributes_t attributes;
          memset(&attributes, 0, sizeof(attributes));

    * Initialize the object to logical zero values by declaring the object as static or global without an explicit initializer, for example:

      .. autocode::
          static psa_key_attributes_t attributes;

    * Initialize the object to the initializer `PSA_KEY_ATTRIBUTES_INIT`, for example:

      .. autocode::
          psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;

    * Assign the result of the function `psa_key_attributes_init()` to the object, for example:

      .. autocode::
          psa_key_attributes_t attributes;
          attributes = psa_key_attributes_init();

    A freshly initialized attribute object contains the following values:

    .. tabularcolumns:: LL

    ==============  =======
    Attribute       Value
    ==============  =======
    lifetime        `PSA_KEY_LIFETIME_VOLATILE`.
    key identifier  `PSA_KEY_ID_NULL` - which is not a valid key identifier.
    type            `PSA_KEY_TYPE_NONE` - meaning that the type is unspecified.
    key size        ``0`` - meaning that the size is unspecified.
    usage flags     ``0`` - which allows no usage except exporting a public key.
    algorithm       `PSA_ALG_NONE` - which does not allow cryptographic usage, but allows exporting.
    ==============  =======

    .. rubric:: Usage

    A typical sequence to create a key is as follows:

    #. Create and initialize an attribute object.
    #. If the key is persistent, call `psa_set_key_id()`. Also call `psa_set_key_lifetime()` to place the key in a non-default location.
    #. Set the key policy with `psa_set_key_usage_flags()` and `psa_set_key_algorithm()`.
    #. Set the key type with `psa_set_key_type()`. Skip this step if copying an existing key with `psa_copy_key()`.
    #. When generating a random key with `psa_generate_key()` or deriving a key with `psa_key_derivation_output_key()`, set the desired key size with `psa_set_key_bits()`.
    #. Call a key creation function: `psa_import_key()`, `psa_generate_key()`, `psa_key_derivation_output_key()` or `psa_copy_key()`. This function reads the attribute object, creates a key with these attributes, and outputs an identifier for the newly created key.
    #. Optionally call `psa_reset_key_attributes()`, now that the attribute object is no longer needed. Currently this call is not required as the attributes defined in this specification do not require additional resources beyond the object itself.

    A typical sequence to query a key's attributes is as follows:

    #. Call `psa_get_key_attributes()`.
    #. Call ``psa_get_key_xxx()`` functions to retrieve the required attribute(s).
    #. Call `psa_reset_key_attributes()` to free any resources that can be used by the attribute object.

    Once a key has been created, it is impossible to change its attributes.

.. macro:: PSA_KEY_ATTRIBUTES_INIT
    :definition: /* implementation-defined value */

    .. summary::
        This macro returns a suitable initializer for a key attribute object of type `psa_key_attributes_t`.

.. function:: psa_key_attributes_init

    .. summary::
        Return an initial value for a key attribute object.

    .. return:: psa_key_attributes_t

.. function:: psa_get_key_attributes

    .. summary::
        Retrieve the attributes of a key.

    .. param:: psa_key_id_t key
        Identifier of the key to query.
    .. param:: psa_key_attributes_t * attributes
        On entry, ``*attributes`` must be in a valid state. On successful return, it contains the attributes of the key. On failure, it is equivalent to a freshly-initialized attribute object.

    .. return:: psa_status_t
    .. retval:: PSA_SUCCESS
    .. retval:: PSA_ERROR_INVALID_HANDLE
    .. 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 has not been previously initialized by `psa_crypto_init()`. It is implementation-dependent whether a failure to initialize results in this error code.

    This function first resets the attribute object as with `psa_reset_key_attributes()`. It then copies the attributes of the given key into the given attribute object.

    .. note::
        This function clears any previous content from the attribute object and therefore expects it to be in a valid state. In particular, if this function is called on a newly allocated attribute object, the attribute object  must be initialized before calling this function.

    .. note::
        This function might allocate memory or other resources. Once this function has been called on an attribute object, `psa_reset_key_attributes()` must be called to free these resources.

.. function:: psa_reset_key_attributes

    .. summary::
        Reset a key attribute object to a freshly initialized state.

    .. param:: psa_key_attributes_t * attributes
        The attribute object to reset.

    .. return:: void

    The attribute object must be initialized as described in the documentation of the type `psa_key_attributes_t` before calling this function. Once the object has been initialized, this function can be called at any time.

    This function frees any auxiliary resources that the object might contain.
