| .. _functionality-overview: |
| |
| Functionality overview |
| ---------------------- |
| |
| This section provides a high-level overview of the functionality provided by the |
| interface defined in this specification. Refer to the `API definition |
| <api-reference>` for a detailed description. |
| |
| `future` describes features that might be included in future versions of this |
| specification. |
| |
| Due to the modularity of the interface, almost every part of the library is |
| optional. The only mandatory function is `psa_crypto_init()`. |
| |
| Library management |
| ~~~~~~~~~~~~~~~~~~ |
| |
| Applications must call `psa_crypto_init()` to initialize the library before |
| using any other function. |
| |
| Key management |
| ~~~~~~~~~~~~~~ |
| |
| Applications always access keys indirectly via an identifier, and can perform |
| operations using a key without accessing the key material. This allows keys to |
| be *non-extractable*, where an application can use a key but is not permitted to |
| obtain the key material. Non-extractable keys are bound to the device, can be |
| rate-limited and can have their usage restricted by policies. |
| |
| Each key has a set of attributes that describe the key and the policy for using |
| the key. A `psa_key_attributes_t` object contains all of the attributes, which |
| is used when creating a key and when querying key attributes. |
| |
| Each key has a *lifetime* that determines when the key material is destroyed. |
| There are two types of lifetimes: `volatile <volatile-keys>` and |
| `persistent <persistent-keys>`. |
| |
| .. _volatile-keys: |
| |
| Volatile keys |
| ^^^^^^^^^^^^^ |
| |
| A *volatile* key exists until it explicitly destroyed with `psa_destroy_key()` |
| or until the application terminates, which conceptually destroys all of its |
| volatile keys. |
| |
| Conceptually, a volatile key is stored in RAM. Volatile keys have the |
| lifetime `PSA_KEY_LIFETIME_VOLATILE`. |
| |
| To create a volatile key: |
| |
| 1. Populate a `psa_key_attributes_t` object with the required type, size, policy |
| and other key attributes. |
| 2. Create the key with `psa_import_key()`, `psa_generate_key()`, |
| `psa_key_derivation_output_key()` or `psa_copy_key()`. If successful, these |
| functions output a transient `key identifier <key-ids>`. |
| |
| To destroy a volatile key, call `psa_destroy_key()` with the key identifier. |
| |
| .. _persistent-keys: |
| |
| Persistent keys |
| ^^^^^^^^^^^^^^^ |
| |
| A *persistent* key exists until it explicitly destroyed with `psa_destroy_key()` |
| or until it is wiped by the reset or destruction of the device. |
| |
| Each persistent key has a permanent key identifier, which acts as a name for the key. |
| Within an application, the key identifier corresponds to a single key. The |
| application specifies the key identifier when the key is created and when |
| using the key. |
| |
| Persistent keys can be stored in different storage areas; this is indicated |
| through different lifetime values. This specification defines a single lifetime |
| value `PSA_KEY_LIFETIME_PERSISTENT` which corresponds to a default storage |
| area. Implementations can define alternative lifetime values corresponding to |
| different storage areas with different retention policies, or to secure elements |
| with different security characteristics. |
| |
| To create a persistent key: |
| |
| 1. Populate a `psa_key_attributes_t` object with the key’s type, size, policy |
| and other attributes. |
| 2. In the attributes object, set the desired lifetime and persistent identifier |
| for the key. |
| 3. Create the key with one of the *key creation functions*: |
| |
| * `psa_import_key()` |
| * `psa_generate_key()` |
| * `psa_key_derivation_output_key()` |
| * `psa_copy_key()` |
| |
| If successful, these functions output the `key identifier <key-ids>` |
| that was specified by the application in step 2. |
| |
| To access an existing persistent key: use the key identifier in any API that |
| requires a key. |
| |
| To remove cached copies of key material for persistent keys created with the |
| `PSA_KEY_USAGE_CACHE` policy: call `psa_purge_key()` with the key identifier. |
| |
| To destroy a persistent key: call `psa_destroy_key()` with the key identifier. |
| Destroying a persistent key permanently removes it from memory and storage. |
| |
| The key lifetime and identifier are set when the key is created and cannot be |
| changed without destroying the key first. If the original key permits copying, |
| then the application can specify a different lifetime for the copy of the key. |
| |
| .. _key-ids: |
| |
| Key identifiers |
| ^^^^^^^^^^^^^^^ |
| |
| Key identifiers are integral values that act as permanent names for persistent |
| keys, or as transient references to volatile keys. Key identifiers use the |
| `psa_key_id_t` type, and the range of identifier values is divided as follows: |
| |
| :code:`PSA_KEY_ID_NULL = 0` |
| 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 must allocate any volatile key identifiers from this range. |
| |
| Key identifiers outside these ranges are reserved for future use. |
| |
| Key identifiers are output from a successful call to one of |
| the key creation functions. For persistent keys, this is the same identifier |
| as the one specified in the key attributes used to create the key. |
| The key identifier remains valid until it is invalidated by passing it to |
| `psa_destroy_key()`. A volatile key identifier must not be used after it has been |
| invalidated. |
| |
| Valid key identifiers must have distinct values within the same application. If |
| the implementation provides `caller isolation <isolation>`, then key |
| identifiers are local to each application. That is, the same key identifier in two |
| applications corresponds to two different keys. |
| |
| If an invalid key identifier is provided as a parameter in any function, the |
| function will return `PSA_ERROR_INVALID_HANDLE`; except for the special case of |
| calling :code:`psa_destroy_key(PSA_KEY_ID_NULL)`, which has no effect and always |
| returns `PSA_SUCCESS`. |
| |
| There must be a matching call to `psa_destroy_key()` for each successful call |
| to a create a volatile key. |
| |
| A call to `psa_destroy_key()` destroys the key material, and will cause any active |
| operations that are using the key to fail. Therefore an application must not |
| destroy a key while an operation using that key is in progress, unless the |
| application is prepared to handle a failure of the operation. |
| |
| Recommendations of minimum standards for key management |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Most implementations provide the following functions: |
| |
| * `psa_import_key()`. The exceptions are implementations that only give access |
| to a key or keys that are provisioned by proprietary means, and do not allow |
| the main application to use its own cryptographic material. |
| |
| * `psa_get_key_attributes()` and the ``psa_get_key_xxx()`` accessor functions. |
| They are easy to implement, and it is difficult to write applications and to |
| diagnose issues without being able to check the metadata. |
| |
| * `psa_export_public_key()`. This function is usually provided if the |
| implementation supports any asymmetric algorithm, since public-key |
| cryptography often requires the delivery of a public key that is associated |
| with a protected private key. |
| |
| * `psa_export_key()`. However, highly constrained implementations that are |
| designed to work only with short-term keys, or only with long-term |
| non-extractable keys, do not need to provide this function. |
| |
| Usage policies |
| ~~~~~~~~~~~~~~ |
| |
| All keys have an associated policy that regulates which operations are permitted |
| on the key. Each key policy is a set of usage flags and a specific algorithm |
| that is permitted with the key. The policy is part of the key attributes that |
| are managed by a `psa_key_attributes_t` object. |
| |
| 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 extractable flag `PSA_KEY_USAGE_EXPORT` determines whether the key |
| material can be extracted. |
| * 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 |
| :title:`key-material`. |
| * The other usage flags, for example, `PSA_KEY_USAGE_ENCRYPT` and `PSA_KEY_USAGE_SIGN_MESSAGE`, |
| determine whether the corresponding operation is permitted on the key. |
| |
| In addition to the usage bitmask, a policy specifies which algorithm is |
| permitted with the key. This specification only defines policies that restrict |
| keys to a single algorithm, which is consistent with both common practice and |
| security good practice. |
| |
| A highly constrained implementation might not be able to support all the policies |
| that can be expressed through this interface. If an implementation cannot create |
| a key with the required policy, it must return an appropriate error code when |
| the key is created. |
| |
| Symmetric cryptography |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This specification defines interfaces for the following types of symmetric |
| cryptographic operation: |
| |
| * Message digests, commonly known as hash functions. |
| * Message authentication codes (MAC). |
| * Symmetric ciphers. |
| * Authenticated encryption with associated data (AEAD). |
| |
| For each type of symmetric cryptographic operation, the API includes: |
| |
| * A pair of *single-part* functions. For example, compute and verify, or |
| encrypt and decrypt. |
| * A series of functions that permit *multi-part operations*. |
| |
| Single-part Functions |
| ^^^^^^^^^^^^^^^^^^^^^ |
| |
| Single-part functions are APIs that implement the cryptographic operation in a |
| single function call. This is the easiest API to use when all of the inputs and |
| outputs fit into the application memory. |
| |
| Some use cases involve messages that are too large to be assembled in memory, or |
| require non-default configuration of the algorithm. These use cases require the |
| use of a :title:`multi-part operation <multi-part-operations>`. |
| |
| .. _multi-part-operations: |
| |
| Multi-part operations |
| ^^^^^^^^^^^^^^^^^^^^^ |
| |
| Multi-part operations are APIs which split a single cryptographic operation into |
| a sequence of separate steps. This enables fine control over the configuration |
| of the cryptographic operation, and allows the message data to be processed in |
| fragments instead of all at once. For example, the following situations require |
| the use of a multi-part operation: |
| |
| - Processing messages that cannot be assembled in memory. |
| - Using a deterministic IV for unauthenticated encryption. |
| - Providing the IV separately for unauthenticated encryption or decryption. |
| - Separating the AEAD authentication tag from the cipher text. |
| |
| Each multi-part operation defines a specific object type to maintain the state |
| of the operation. These types are implementation-defined. All multi-part |
| operations follow the same pattern of use: |
| |
| 1. **Allocate:** Allocate memory for an operation object of the appropriate |
| type. The application can use any allocation strategy: stack, heap, static, etc. |
| |
| 2. **Initialize:** Initialize or assign the operation object by one of the |
| following methods: |
| |
| - Set it to logical zero. This is automatic for static and global |
| variables. Explicit initialization must use the associated |
| ``PSA_xxx_INIT`` macro as the type is implementation-defined. |
| - Set it to all-bits zero. This is automatic if the object was |
| allocated with ``calloc()``. |
| - Assign the value of the associated macro ``PSA_xxx_INIT``. |
| - Assign the result of calling the associated function |
| ``psa_xxx_init()``. |
| |
| The resulting object is now *inactive*. |
| |
| It is an error to initialize an operation object that is in *active* or |
| *error* states. This can leak memory or other resources. |
| |
| 3. **Setup:** Start a new multi-part operation on an *inactive* operation |
| object. Each operation object will define one or more setup functions to |
| start a specific operation. |
| |
| On success, a setup function will put an operation object into an *active* |
| state. On failure, the operation object will remain *inactive*. |
| |
| 4. **Update:** Update an *active* operation object. The update function can |
| provide additional parameters, supply data for processing or generate |
| outputs. |
| |
| On success, the operation object remains *active*. On failure, the |
| operation object will enter an *error* state. |
| |
| 5. **Finish:** To end the operation, call the applicable finishing function. |
| This will take any final inputs, produce any final outputs, and then |
| release any resources associated with the operation. |
| |
| On success, the operation object returns to the *inactive* state. On |
| failure, the operation object will enter an *error* state. |
| |
| An operation can be aborted at any stage during its use by calling the |
| associated ``psa_xxx_abort()`` function. This will release any resources |
| associated with the operation and return the operation object to the *inactive* |
| state. |
| |
| Any error that occurs to an operation while it is in an *active* state will |
| result in the operation entering an *error* state. The application must call the |
| associated ``psa_xxx_abort()`` function to release the operation resources and |
| return the object to the *inactive* state. |
| |
| Once an operation object is returned to the *inactive* state, it can be reused |
| by calling one of the applicable setup functions again. |
| |
| If a multi-part operation object is not initialized before use, the behavior is |
| undefined. |
| |
| If a multi-part operation function determines that the operation object is not in |
| any valid state, it can return `PSA_ERROR_CORRUPTION_DETECTED`. |
| |
| If a multi-part operation function is called with an operation object in the |
| wrong state, the function will return `PSA_ERROR_BAD_STATE` and the operation |
| object will enter the *error* state. |
| |
| It is safe to move a multi-part operation object to a different memory location, |
| for example, using a bitwise copy, and then to use the object in the new |
| location. For example, an application can allocate an operation object on the |
| stack and return it, or the operation object can be allocated within memory |
| managed by a garbage collector. However, this does not permit the following |
| behaviors: |
| |
| - Moving the object while a function is being called on the object. This is |
| not safe. See also `concurrency`. |
| - Working with both the original and the copied operation objects. This |
| requires cloning the operation, which is only available for hash operations |
| using `psa_hash_clone()`. |
| |
| Each type of multi-part operation can have multiple *active* states. |
| Documentation for the specific operation describes the configuration and update |
| functions, and any requirements about their usage and ordering. |
| |
| Message digests (Hashes) |
| ^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The single-part hash functions are: |
| |
| - `psa_hash_compute()` to calculate the hash of a message. |
| - `psa_hash_compare()` to compare the hash of a message with a reference value. |
| |
| The `psa_hash_operation_t` `multi-part operation <multi-part-operations>` |
| allows messages to be processed in fragments: |
| |
| 1. Initialize the `psa_hash_operation_t` object to zero, or by assigning the |
| value of the associated macro `PSA_HASH_OPERATION_INIT`. |
| 2. Call `psa_hash_setup()` to specify the required hash algorithm, call |
| `psa_hash_clone()` to duplicate the state of *active* `psa_hash_operation_t` |
| object, or call `psa_hash_resume()` to restart a hash operation with the |
| output from a previously suspended hash operation. |
| 3. Call the `psa_hash_update()` function on successive chunks of the message. |
| 4. At the end of the message, call the required finishing function: |
| |
| - To suspend the hash operation and extract a hash suspend state, |
| call `psa_hash_suspend()`. The output state can subsequently be used |
| to resume the hash operation. |
| - To calculate the digest of a message, call `psa_hash_finish()`. |
| - To verify the digest of a message against a reference value, call |
| `psa_hash_verify()`. |
| |
| To abort the operation or recover from an error, call `psa_hash_abort()`. |
| |
| Message authentication codes (MACs) |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The single-part MAC functions are: |
| |
| - `psa_mac_compute()` to calculate the MAC of a message. |
| - `psa_mac_verify()` to compare the MAC of a message with a reference value. |
| |
| The `psa_mac_operation_t` `multi-part operation <multi-part-operations>` |
| allows messages to be processed in fragments: |
| |
| 1. Initialize the `psa_mac_operation_t` object to zero, or by assigning the |
| value of the associated macro `PSA_MAC_OPERATION_INIT`. |
| 2. Call `psa_mac_sign_setup()` or `psa_mac_verify_setup()` to specify the |
| algorithm and key. |
| 3. Call the `psa_mac_update()` function on successive chunks of the message. |
| 4. At the end of the message, call the required finishing function: |
| |
| - To calculate the MAC of the message, call `psa_mac_sign_finish()`. |
| - To verify the MAC of the message against a reference value, call |
| `psa_mac_verify_finish()`. |
| |
| To abort the operation or recover from an error, call `psa_mac_abort()`. |
| |
| Encryption and decryption |
| ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| .. note:: |
| |
| The unauthenticated cipher API is provided to implement legacy protocols and |
| for use cases where the data integrity and authenticity is guaranteed by |
| non-cryptographic means. It is recommended that newer protocols use |
| :title:`func-aead`. |
| |
| The single-part functions for encrypting or decrypting a message using an |
| unauthenticated symmetric cipher are: |
| |
| - `psa_cipher_encrypt()` to encrypt a message using an unauthenticated symmetric |
| cipher. The encryption function generates a random IV. Use the multi-part API |
| to provide a deterministic IV: this is not secure in general, but |
| can be secure in some conditions that depend on the algorithm. |
| - `psa_cipher_decrypt()` to decrypt a message using an unauthenticated symmetric |
| cipher. |
| |
| The `psa_cipher_operation_t` `multi-part operation <multi-part-operations>` |
| permits alternative initialization parameters and allows messages to be |
| processed in fragments: |
| |
| 1. Initialize the `psa_cipher_operation_t` object to zero, or by assigning the |
| value of the associated macro `PSA_CIPHER_OPERATION_INIT`. |
| 2. Call `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` to specify the |
| algorithm and key. |
| 3. Provide additional parameters: |
| |
| - When encrypting data, generate or set an initialization vector (IV), |
| nonce, or similar initial value such as an initial counter value. To |
| generate a random IV, which is recommended in most protocols, call |
| `psa_cipher_generate_iv()`. To set the IV, call `psa_cipher_set_iv()`. |
| - When decrypting, set the IV or nonce. To set the IV, call |
| `psa_cipher_set_iv()`. |
| 4. Call the `psa_cipher_update()` function on successive chunks of the message. |
| 5. Call `psa_cipher_finish()` to complete the operation and return any final |
| output. |
| |
| To abort the operation or recover from an error, call `psa_cipher_abort()`. |
| |
| .. _func-aead: |
| |
| Authenticated encryption (AEAD) |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The single-part AEAD functions are: |
| |
| - `psa_aead_encrypt()` to encrypt a message using an authenticated symmetric |
| cipher. |
| - `psa_aead_decrypt()` to decrypt a message using an authenticated symmetric |
| cipher. |
| |
| These functions follow the interface recommended by :RFC:`5116`. |
| |
| The encryption function requires a nonce to be provided. To generate a random |
| nonce, either call `psa_generate_random()` or use the AEAD multi-part API. |
| |
| The `psa_aead_operation_t` `multi-part operation <multi-part-operations>` |
| permits alternative initialization parameters and allows messages to be |
| processed in fragments: |
| |
| 1. Initialize the `psa_aead_operation_t` object to zero, or by assigning the |
| value of the associated macro `PSA_AEAD_OPERATION_INIT`. |
| 2. Call `psa_aead_encrypt_setup()` or `psa_aead_decrypt_setup()` to specify the |
| algorithm and key. |
| 3. Provide additional parameters: |
| |
| - If the algorithm requires it, call `psa_aead_set_lengths()` to specify the |
| length of the non-encrypted and encrypted inputs to the operation. |
| - When encrypting, call either `psa_aead_generate_nonce()` or |
| `psa_aead_set_nonce()` to generate or set the nonce. |
| - When decrypting, call `psa_aead_set_nonce()` to set the nonce. |
| 4. Call `psa_aead_update_ad()` zero or more times with fragments of the |
| non-encrypted additional data. |
| 5. Call `psa_aead_update()` zero or more times with fragments of the plaintext |
| or ciphertext to encrypt or decrypt. |
| 6. At the end of the message, call the required finishing function: |
| |
| - To complete an encryption operation, call `psa_aead_finish()` to compute |
| and return authentication tag. |
| - To complete a decryption operation, call `psa_aead_verify()` to |
| compute the authentication tag and verify it against a reference value. |
| |
| To abort the operation or recover from an error, call `psa_aead_abort()`. |
| |
| Having a multi-part interface to authenticated encryption raises specific issues. |
| |
| Multi-part authenticated decryption produces partial results that are not |
| authenticated. Applications must not use or expose partial results of |
| authenticated decryption until `psa_aead_verify()` has returned a success |
| status and must destroy all partial results without revealing them if |
| `psa_aead_verify()` returns a failure status. Revealing partial results, either directly or indirectly through the application’s behavior, can compromise the |
| confidentiality of all inputs that are encrypted with the same key. |
| |
| For encryption, some common algorithms cannot be processed in a streaming |
| fashion. For SIV mode, the whole plaintext must be known before the encryption |
| can start; the multi-part AEAD API is not meant to be usable with SIV mode. For |
| CCM mode, the length of the plaintext must be known before the encryption can |
| start; the application can call the function `psa_aead_set_lengths()` to provide |
| these lengths before providing input. |
| |
| .. _key-derivation: |
| |
| Key derivation |
| ^^^^^^^^^^^^^^ |
| |
| A key derivation encodes a deterministic method to generate a finite stream of |
| bytes. This data stream is computed by the cryptoprocessor and extracted in |
| chunks. If two key derivation operations are constructed with the same |
| parameters, then they produce the same output. |
| |
| A key derivation consists of two phases: |
| |
| 1. Input collection. This is sometimes known as *extraction*: the operation |
| “extracts” information from the inputs to generate a pseudorandom |
| intermediate secret value. |
| 2. Output generation. This is sometimes known as *expansion*: the operation |
| “expands” the intermediate secret value to the desired output length. |
| |
| The specification defines a `multi-part operation <multi-part-operations>` |
| API for key derivation that allows for multiple key and non-key outputs to be |
| extracted from a single derivation operation object. |
| |
| In an implementation with `isolation <isolation>`, the intermediate |
| state of the key derivation is not visible to the caller, and if an output of |
| the derivation is a non-exportable key, then this key cannot be recovered |
| outside the isolation boundary. |
| |
| Applications use the `psa_key_derivation_operation_t` type to create key |
| derivation operations. The operation object is used as follows: |
| |
| 1. Initialize a `psa_key_derivation_operation_t` object to zero or to |
| `PSA_KEY_DERIVATION_OPERATION_INIT`. |
| 2. Call `psa_key_derivation_setup()` to select a key derivation algorithm. |
| 3. Call the functions `psa_key_derivation_input_bytes()` and |
| `psa_key_derivation_input_key()`, or `psa_key_derivation_key_agreement()` to |
| provide the inputs to the key derivation algorithm. Many key derivation |
| algorithms take multiple inputs; the ``step`` parameter to these functions |
| indicates which input is being provided. The documentation for each key |
| derivation algorithm describes the expected inputs for that algorithm and |
| in what order to pass them. |
| 4. Optionally, call `psa_key_derivation_set_capacity()` to set a limit on the |
| amount of data that can be output from the key derivation operation. |
| 5. Call `psa_key_derivation_output_key()` to create a derived key, or |
| `psa_key_derivation_output_bytes()` to export the derived data. These |
| functions can be called multiple times to read successive output from the key |
| derivation, until the stream is exhausted when its capacity has been reached. |
| 6. Key derivation does not finish in the same way as other multi-part |
| operations. Call `psa_key_derivation_abort()` to release the key derivation |
| operation memory when the object is no longer required. |
| |
| To recover from an error, call `psa_key_derivation_abort()` to release the key |
| derivation operation memory. |
| |
| A key derivation operation cannot be rewound. Once a part of the stream has been |
| output, it cannot be output again. This ensures that the same part of the output |
| will not be used for different purposes. |
| |
| Example of the symmetric cryptography API |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Here is an example of a use case where a master key is used to generate both a |
| message encryption key and an IV for the encryption, and the derived key and IV |
| are then used to encrypt a message. |
| |
| 1. Derive the message encryption material from the master key. |
| |
| 1. Initialize a `psa_key_derivation_operation_t` object to zero or to |
| `PSA_KEY_DERIVATION_OPERATION_INIT`. |
| 2. Call `psa_key_derivation_setup()` with `PSA_ALG_HKDF` as the algorithm. |
| 3. Call `psa_key_derivation_input_key()` with the step |
| `PSA_KEY_DERIVATION_INPUT_SECRET` and the master key. |
| 4. Call `psa_key_derivation_input_bytes()` with the step |
| `PSA_KEY_DERIVATION_INPUT_INFO` and a public value that uniquely |
| identifies the message. |
| 5. Populate a `psa_key_attributes_t` object with the derived message |
| encryption key’s attributes. |
| 6. Call `psa_key_derivation_output_key()` to create the derived message key. |
| 7. Call `psa_key_derivation_output_bytes()` to generate the derived IV. |
| 8. Call `psa_key_derivation_abort()` to release the key derivation operation |
| memory. |
| |
| 2. Encrypt the message with the derived material. |
| |
| 1. Initialize a `psa_cipher_operation_t` object to zero or to |
| `PSA_CIPHER_OPERATION_INIT`. |
| 2. Call `psa_cipher_encrypt_setup()` with the derived message encryption key. |
| 3. Call `psa_cipher_set_iv()` using the derived IV retrieved above. |
| 4. Call `psa_cipher_update()` one or more times to encrypt the message. |
| 5. Call `psa_cipher_finish()` at the end of the message. |
| |
| 3. Call `psa_destroy_key()` to clear the generated key. |
| |
| Asymmetric cryptography |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This specification defines functions for asymmetric cryptography, including |
| asymmetric encryption, asymmetric signature, and two-way key agreement. |
| |
| Asymmetric encryption |
| ^^^^^^^^^^^^^^^^^^^^^ |
| |
| Asymmetric encryption is provided through the functions |
| `psa_asymmetric_encrypt()` and `psa_asymmetric_decrypt()`. |
| |
| Hash-and-sign |
| ^^^^^^^^^^^^^ |
| |
| The signature and verification functions `psa_sign_message()` and |
| `psa_verify_message()` take a message as one of their inputs and perform a |
| hash-and-sign algorithm. |
| |
| The functions `psa_sign_hash()` and `psa_verify_hash()` take a message hash as |
| one of their inputs. This is useful for signing pre-computed hashes, or for |
| implementing hash-and-sign using a :ref:`multi-part hash operation <hash-mp>` |
| before signing the resulting hash. To determine which |
| hash algorithm to use, call the macro `PSA_ALG_GET_HASH()` on the |
| corresponding signature algorithm. |
| |
| Some hash-and-sign algorithms add padding to the message hash before completing |
| the signing operation. The format of the padding that is used depends on the |
| algorithm used to construct the signature. |
| |
| Key agreement |
| ^^^^^^^^^^^^^ |
| |
| This specification defines two functions for a Diffie-Hellman-style key |
| agreement where each party combines its own private key with the peer’s public |
| key. |
| |
| The recommended approach is to use a `key derivation |
| operation <key-derivation>` with the `psa_key_derivation_key_agreement()` |
| input function, which calculates a shared secret for the key derivation |
| function. |
| |
| Where an application needs direct access to the shared secret, it can call |
| `psa_raw_key_agreement()` instead. Note that in general the shared secret is not |
| directly suitable for use as a key because it is biased. |
| |
| Randomness and key generation |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| We strongly recommended that implementations include a random generator, |
| consisting of a cryptographically secure pseudo-random generator (CSPRNG), which |
| is adequately seeded with a cryptographic-quality hardware entropy source, |
| commonly referred to as a true random number generator (TRNG). Constrained |
| implementations can omit the random generation functionality if they do not |
| implement any algorithm that requires randomness internally, and they do not |
| provide a key generation functionality. For example, a special-purpose component |
| for signature verification can omit this. |
| |
| It is recommended that applications use `psa_generate_key()`, |
| `psa_cipher_generate_iv()` or `psa_aead_generate_nonce()` to generate |
| suitably-formatted random data, as applicable. In addition, the API includes a |
| function `psa_generate_random()` to generate and extract arbitrary random data. |