From 09e692345b75fd7475570806669c84c2fa705579 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 28 Jan 2026 21:19:55 +0000 Subject: [PATCH 1/2] Add missing operation types to the Functionality chapter --- doc/crypto/overview/functionality.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/crypto/overview/functionality.rst b/doc/crypto/overview/functionality.rst index e61d4ad3..1403dce6 100644 --- a/doc/crypto/overview/functionality.rst +++ b/doc/crypto/overview/functionality.rst @@ -229,9 +229,11 @@ This specification defines interfaces for the following types of symmetric cryptographic operation: * Message digests, commonly known as hash functions. See :secref:`hashes`. +* Extendable-output functions (XOF). See :secref:`xof`. * Message authentication codes (MAC). See :secref:`macs`. * Symmetric ciphers. See :secref:`ciphers`. * Authenticated encryption with associated data (AEAD). See :secref:`aead`. +* Key wrapping. See :secref:`key-wrapping`. * Key derivation. See :secref:`kdf`. Key derivation only provides multi-part operation, to support the flexibility required by these type of algorithms. @@ -269,15 +271,15 @@ Asymmetric cryptography This specification defines interfaces for the following types of asymmetric cryptographic operation: -* Asymmetric encryption (also known as public-key encryption). See :secref:`pke`. * Asymmetric signature. See :secref:`sign`. +* Asymmetric encryption (also known as public-key encryption). See :secref:`pke`. * Two-way key agreement (also known as key establishment). See :secref:`key-agreement`. * Key encapsulation. See :secref:`key-encapsulation`. * Password-authenticated key exchange (PAKE). See :secref:`pake`. -For asymmetric encryption, the API provides *single-part* functions. +For asymmetric signature, the API provides *single-part* functions. -For asymmetric signature, the API provides single-part functions. +For asymmetric encryption, the API provides single-part functions. For key agreement, the API provides single-part functions and an additional input method for a key-derivation operation. From a2c823fcadc279e062f43d2de44b112f7bf801d3 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 28 Jan 2026 23:02:27 +0000 Subject: [PATCH 2/2] Add multi-part operations for asymmetric signature --- doc/crypto/api.db/psa/crypto.h | 35 +- doc/crypto/api/ops/signature.rst | 539 +++++++++++++++++++++++++- doc/crypto/appendix/history.rst | 3 + doc/crypto/overview/functionality.rst | 6 +- 4 files changed, 568 insertions(+), 15 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index fc17def6..28e11a7c 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2018-2025 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2018-2026 Arm Limited and/or its affiliates // SPDX-License-Identifier: Apache-2.0 typedef /* implementation-defined type */ psa_aead_operation_t; @@ -24,6 +24,8 @@ typedef uint32_t psa_pake_primitive_t; typedef uint8_t psa_pake_primitive_type_t; typedef uint8_t psa_pake_role_t; typedef uint8_t psa_pake_step_t; +typedef /* implementation-defined type */ psa_sign_operation_t; +typedef /* implementation-defined type */ psa_verify_operation_t; typedef /* implementation-defined type */ psa_xof_operation_t; typedef struct psa_custom_key_parameters_t { uint32_t flags; @@ -232,7 +234,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ /* implementation-defined value */ #define PSA_CRYPTO_API_VERSION_MAJOR 1 -#define PSA_CRYPTO_API_VERSION_MINOR 4 +#define PSA_CRYPTO_API_VERSION_MINOR 5 #define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 } #define PSA_DH_FAMILY_RFC3526 ((psa_dh_family_t) 0x05) #define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) @@ -415,10 +417,12 @@ typedef struct psa_custom_key_parameters_t { #define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ /* implementation-defined value */ #define PSA_SIGNATURE_MAX_SIZE /* implementation-defined value */ +#define PSA_SIGN_OPERATION_INIT /* implementation-defined value */ #define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ /* implementation-defined value */ #define PSA_TLS12_ECJPAKE_TO_PMS_OUTPUT_SIZE 32 #define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE /* implementation-defined value */ +#define PSA_VERIFY_OPERATION_INIT /* implementation-defined value */ #define PSA_WRAP_KEY_OUTPUT_SIZE(wrap_key_type, alg, key_type, key_bits) \ /* implementation-defined value */ #define PSA_WRAP_KEY_PAIR_MAX_SIZE /* implementation-defined value */ @@ -767,6 +771,11 @@ void psa_set_key_type(psa_key_attributes_t * attributes, psa_key_type_t type); void psa_set_key_usage_flags(psa_key_attributes_t * attributes, psa_key_usage_t usage_flags); +psa_status_t psa_sign_abort(psa_sign_operation_t * operation); +psa_status_t psa_sign_finish(psa_sign_operation_t * operation, + uint8_t * signature, + size_t signature_size, + size_t * signature_length); psa_status_t psa_sign_hash(psa_key_id_t key, psa_algorithm_t alg, const uint8_t * hash, @@ -799,12 +808,23 @@ psa_status_t psa_sign_message_with_context(psa_key_id_t key, uint8_t * signature, size_t signature_size, size_t * signature_length); +psa_sign_operation_t psa_sign_operation_init(void); +psa_status_t psa_sign_setup(psa_sign_operation_t * operation, + psa_key_id_t key, + psa_algorithm_t alg, + const uint8_t * context, + size_t context_length); +psa_status_t psa_sign_update(psa_sign_operation_t * operation, + const uint8_t * input, + size_t input_length); psa_status_t psa_unwrap_key(const psa_key_attributes_t * attributes, psa_key_id_t wrapping_key, psa_algorithm_t alg, const uint8_t * data, size_t data_length, psa_key_id_t * key); +psa_status_t psa_verify_abort(psa_verify_operation_t * operation); +psa_status_t psa_verify_finish(psa_verify_operation_t * operation); psa_status_t psa_verify_hash(psa_key_id_t key, psa_algorithm_t alg, const uint8_t * hash, @@ -833,6 +853,17 @@ psa_status_t psa_verify_message_with_context(psa_key_id_t key, size_t context_length, const uint8_t * signature, size_t signature_length); +psa_verify_operation_t psa_verify_operation_init(void); +psa_status_t psa_verify_setup(psa_verify_operation_t * operation, + psa_key_id_t key, + psa_algorithm_t alg, + const uint8_t * context, + size_t context_length, + const uint8_t * signature, + size_t signature_length); +psa_status_t psa_verify_update(psa_verify_operation_t * operation, + const uint8_t * input, + size_t input_length); psa_status_t psa_wrap_key(psa_key_id_t wrapping_key, psa_algorithm_t alg, psa_key_id_t key, diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 43294969..e592c5d6 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -98,6 +98,21 @@ The |API| provides several functions for calculating and verifying signatures: See :secref:`single-part-signature`. +.. rubric:: Signature multi-part operations + +For large or streamed messages, it might be necessary to compute or verify a signature without having the entire message available at once. + +* For hash-and-sign signature algorithms, this has been possible since version 1.0 of the |API| by using a multi-part hash operation followed by a call to `psa_sign_hash()` or `psa_verify_hash()`. +* Version 1.5 of the |API| introduces multi-part signature operations, `psa_sign_operation_t` and `psa_verify_operation_t`, that enable many more signature algorithms to be used with a fragmented message, including some of the message signature algorithms. + + .. note:: + Message signature algorithms that require the message data to be processed more than once cannot be used in a multi-part operation, and can only be used with the single-part functions. + For example, the PureEdDSA algorithms cannot be used with multi-part sign operation, but can be used with a multi-part verify operation. + + See the individual algorithm descriptions for details. + +See :secref:`multi-part-signature`. + .. _rsa-sign-algorithms: RSA signature algorithms @@ -120,6 +135,7 @@ RSA signature algorithms This hash-and-sign signature algorithm can be used with both the message and hash signature functions. RSA PKCS#1 v1.5 does not have a context parameter. However, the sign or verify with context functions can be used with a zero-length context. + This algorithm can be used with the multi-part sign and verify operations. This signature scheme is defined by :RFC-title:`8017#8.2` under the name RSASSA-PKCS1-v1_5. @@ -213,6 +229,7 @@ RSA signature algorithms This hash-and-sign signature algorithm can be used with both the message and hash signature functions. RSA PSS does not have a context parameter. However, the sign or verify with context functions can be used with a zero-length context. + This algorithm can be used with the multi-part sign and verify operations. This algorithm is randomized: each invocation returns a different, equally valid signature. @@ -254,6 +271,7 @@ RSA signature algorithms This hash-and-sign signature algorithm can be used with both the message and hash signature functions. RSA PSS does not have a context parameter. However, the sign or verify with context functions can be used with a zero-length context. + This algorithm can be used with the multi-part sign and verify operations. This algorithm is randomized: each invocation returns a different, equally valid signature. @@ -367,6 +385,7 @@ ECDSA signature algorithms This hash-and-sign signature algorithm can be used with both the message and hash signature functions. ECDSA does not have a context parameter. However, the sign or verify with context functions can be used with a zero-length context. + This algorithm can be used with the multi-part sign and verify operations. When used with `psa_sign_hash()` or `psa_verify_hash()`, the provided ``hash`` parameter is the message digest, computed using the ``hash_alg`` hash algorithm. @@ -449,6 +468,7 @@ ECDSA signature algorithms This hash-and-sign signature algorithm can be used with both the message and hash signature functions. ECDSA does not have a context parameter. However, the sign or verify with context functions can be used with a zero-length context. + This algorithm can be used with the multi-part sign and verify operations. When used with `psa_sign_hash()` or `psa_verify_hash()`, the provided ``hash`` parameter is the message digest, computed using the ``hash_alg`` hash algorithm. @@ -581,6 +601,7 @@ The development of EdDSA resulted in a total of five distinct algorithms: This message-signature algorithm can be used with the `psa_sign_message()` and `psa_verify_message()` functions. With a zero-length context, `PSA_ALG_PURE_EDDSA` can also be used with the `psa_sign_message_with_context()` and `psa_verify_message_with_context()` functions. It cannot be used to sign hashes. + This algorithm can be used with the multi-part verify operation, but not with the multi-part sign operation. This is the PureEdDSA digital signature algorithm defined by :RFC-title:`8032`, with zero-length context. @@ -617,6 +638,7 @@ The development of EdDSA resulted in a total of five distinct algorithms: This message-signature algorithm can be used with both the message and message with context signature functions. It cannot be used to sign hashes. + This algorithm can be used with the multi-part verify operation, but not with the multi-part sign operation. This is the PureEdDSA digital signature algorithm defined by :RFC-title:`8032`, with a context parameter. The context parameter can be between zero and 255 bytes in length. @@ -647,6 +669,7 @@ The development of EdDSA resulted in a total of five distinct algorithms: * Call `psa_sign_message()` or `psa_sign_message_with_context()` with the message. Verifying a signature is similar, using `psa_verify_message()` or `psa_verify_message_with_context()`. + A signature of a fragmented message can be verified using a `psa_verify_operation_t` multi-part verify operation. .. subsection:: Compatible key types @@ -662,6 +685,7 @@ The development of EdDSA resulted in a total of five distinct algorithms: .. versionadded:: 1.1 This hash-and-sign signature algorithm can be used with both the message and hash signature functions. + This algorithm can be used with the multi-part sign and verify operations. This calculates the Ed25519ph algorithm as specified in :RFC-title:`8032#5.1`, and requires an Edwards25519 curve key. @@ -679,6 +703,8 @@ The development of EdDSA resulted in a total of five distinct algorithms: * Call `psa_sign_message()` or `psa_sign_message_with_context()` with the message. + * Use a `psa_sign_operation_t` multi-part sign operation. + * Calculate the SHA-512 hash of the message with `psa_hash_compute()`, or with a multi-part hash operation, using the hash algorithm `PSA_ALG_SHA_512`. Then sign the calculated hash with `psa_sign_hash()` or `psa_sign_hash_with_context()`. @@ -686,6 +712,8 @@ The development of EdDSA resulted in a total of five distinct algorithms: * Call `psa_verify_message()`, or `psa_verify_message_with_context()` with the message. + * Use a `psa_verify_operation_t` multi-part verify operation. + * Calculate the SHA-512 hash of the message with `psa_hash_compute()`, or with a multi-part hash operation, using the hash algorithm `PSA_ALG_SHA_512`. Then sign the calculated hash with `psa_verify_hash()` or `psa_verify_hash_with_context()`. @@ -707,6 +735,7 @@ The development of EdDSA resulted in a total of five distinct algorithms: .. versionadded:: 1.1 This hash-and-sign signature algorithm can be used with both the message and hash signature functions. + This algorithm can be used with the multi-part sign and verify operations. This calculates the Ed448ph algorithm as specified in :RFC-title:`8032#5.2`, and requires an Edwards448 curve key. @@ -724,6 +753,8 @@ The development of EdDSA resulted in a total of five distinct algorithms: * Call `psa_sign_message()`, or `psa_sign_message_with_context()` with the message. + * Use a `psa_sign_operation_t` multi-part sign operation. + * Calculate the first 64 bytes of the SHAKE256 output of the message with `psa_hash_compute()`, or with a multi-part hash operation, using the hash algorithm `PSA_ALG_SHAKE256_512`. Then sign the calculated hash with `psa_sign_hash()` or `psa_sign_hash_with_context()`. @@ -731,6 +762,8 @@ The development of EdDSA resulted in a total of five distinct algorithms: * Call `psa_verify_message()`, or `psa_verify_message_with_context()` with the message. + * Use a `psa_verify_operation_t` multi-part verify operation. + * Calculate the first 64 bytes of the SHAKE256 output of the message with `psa_hash_compute()`, or with a multi-part hash operation, using the hash algorithm `PSA_ALG_SHAKE256_512`. Then sign the calculated hash with `psa_verify_hash()` or `psa_verify_hash_with_context()`. @@ -762,8 +795,8 @@ The development of EdDSA resulted in a total of five distinct algorithms: .. _single-part-signature: -Asymmetric signature functions ------------------------------- +Single-part asymmetric signature functions +------------------------------------------ .. function:: psa_sign_message @@ -827,8 +860,11 @@ Asymmetric signature functions To provide a context value, use `psa_sign_message_with_context()` instead. .. note:: - To perform a multi-part hash-and-sign signature algorithm, first use a :ref:`multi-part hash operation ` and then pass the resulting hash to `psa_sign_hash()`. - :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. + To calculate a signature for a fragmented message, either: + + * From version 1.5 of the |API|, use a `psa_sign_operation_t` multi-part sign operation. + * For a hash-and-sign signature algorithm, use a `psa_hash_operation_t` multi-part hash operation and then pass the resulting hash to `psa_sign_hash()`. + :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. .. function:: psa_sign_message_with_context @@ -900,8 +936,11 @@ Asymmetric signature functions If a context parameter is not required, `psa_sign_message()` can be used instead. .. note:: - To perform a multi-part hash-and-sign signature algorithm, first use a :ref:`multi-part hash operation ` and then pass the resulting hash to `psa_sign_hash_with_context()`. - :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. + To calculate a signature for a fragmented message, either: + + * From version 1.5 of the |API|, use a `psa_sign_operation_t` multi-part sign operation. + * For a hash-and-sign signature algorithm, use a `psa_hash_operation_t` multi-part hash operation and then pass the resulting hash to `psa_sign_hash_with_context()`. + :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. .. function:: psa_verify_message @@ -957,8 +996,11 @@ Asymmetric signature functions To provide a context value, use `psa_verify_message_with_context()` instead. .. note:: - To perform a multi-part hash-and-sign signature verification algorithm, first use a :ref:`multi-part hash operation ` to hash the message and then pass the resulting hash to `psa_verify_hash()`. - :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. + To verify a signature for a fragmented message, either: + + * From version 1.5 of the |API|, use a `psa_verify_operation_t` multi-part verify operation. + * For a hash-and-sign signature algorithm, use a `psa_hash_operation_t` multi-part hash operation and then pass the resulting hash to `psa_verify_hash()`. + :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. .. function:: psa_verify_message_with_context @@ -1022,8 +1064,11 @@ Asymmetric signature functions If a context parameter is not required, `psa_verify_message()` can be used instead. .. note:: - To perform a multi-part hash-and-sign signature verification algorithm, first use a :ref:`multi-part hash operation ` to hash the message and then pass the resulting hash to `psa_verify_hash_with_context()`. - :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. + To verify a signature for a fragmented message, either: + + * From version 1.5 of the |API|, use a `psa_verify_operation_t` multi-part verify operation. + * For a hash-and-sign signature algorithm, use a `psa_hash_operation_t` multi-part hash operation and then pass the resulting hash to `psa_verify_hash_with_context()`. + :code:`PSA_ALG_GET_HASH(alg)` can be used to determine the hash algorithm to use. .. function:: psa_sign_hash @@ -1303,6 +1348,480 @@ Asymmetric signature functions If a context parameter is not required, `psa_verify_hash()` can be used instead. +.. _multi-part-signature: + +Multi-part asymmetric signature operations +------------------------------------------ + +.. typedef:: /* implementation-defined type */ psa_sign_operation_t + + .. summary:: + The type of the state object for multi-part sign operations. + + .. versionadded:: 1.5 + + Before calling any function on a sign operation object, the application must initialize it by any of the following means: + + * Set the object to all-bits-zero, for example: + + .. code-block:: xref + + psa_sign_operation_t operation; + memset(&operation, 0, sizeof(operation)); + + * Initialize the object to logical zero values by declaring the object as static or global without an explicit initializer, for example: + + .. code-block:: xref + + static psa_sign_operation_t operation; + + * Initialize the object to the initializer `PSA_SIGN_OPERATION_INIT`, for example: + + .. code-block:: xref + + psa_sign_operation_t operation = PSA_SIGN_OPERATION_INIT; + + * Assign the result of the function `psa_sign_operation_init()` to the object, for example: + + .. code-block:: xref + + psa_sign_operation_t operation; + operation = psa_sign_operation_init(); + + This is an implementation-defined type. + Applications that make assumptions about the content of this object will result in implementation-specific behavior, and are non-portable. + +.. macro:: PSA_SIGN_OPERATION_INIT + :definition: /* implementation-defined value */ + + .. summary:: + This macro returns a suitable initializer for a sign operation object of type `psa_sign_operation_t`. + + .. versionadded:: 1.5 + +.. function:: psa_sign_operation_init + + .. summary:: + Return an initial value for a sign operation object. + + .. versionadded:: 1.5 + + .. return:: psa_sign_operation_t + +.. function:: psa_sign_setup + + .. summary:: + Set up a multi-part sign operation. + + .. versionadded:: 1.5 + + .. param:: psa_sign_operation_t * operation + The operation object to set up. + It must have been initialized as per the documentation for `psa_sign_operation_t` and not yet in use. + .. param:: psa_key_id_t key + Identifier of the key to use for the operation. + It must be an asymmetric key pair. + It must remain valid until the operation terminates. + The key must permit the usage `PSA_KEY_USAGE_SIGN_MESSAGE`. + .. param:: psa_algorithm_t alg + An asymmetric signature algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_SIGN_MESSAGE(alg)` is true. + .. param:: const uint8_t * context + The context to use for this signature. + .. param:: size_t context_length + Size of the ``context`` buffer in bytes. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The operation is now active. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The key does not have the `PSA_KEY_USAGE_SIGN_MESSAGE` flag, or it does not permit the requested algorithm. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported, or is not an asymmetric signature algorithm that permits signing a message. + * ``key`` is not supported for use with ``alg``. + * The implementation does not support this value of ``context_length`` for ``alg``. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not an asymmetric signature algorithm that permits signing a message with a non-zero-length context. + * ``key`` is not an asymmetric key pair, that is compatible with ``alg``. + * ``context_length`` is not valid for the algorithm and key type. + * ``context`` is not a valid input value for the algorithm and key type. + .. 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_INSUFFICIENT_ENTROPY + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be inactive. + * The library requires initializing by a call to `psa_crypto_init()`. + + If a context parameter is not required or not supported by the algorithm, a zero-length context must be provided. + + The sequence of operations to sign a message is as follows: + + 1. Allocate a sign operation object which will be passed to all the functions listed here. + #. Initialize the operation object with one of the methods described in the documentation for `psa_sign_operation_t`, for example `PSA_SIGN_OPERATION_INIT`. + #. Call `psa_sign_setup()` to specify the key-pair, algorithm, and optional context value. + #. Call `psa_sign_update()` zero, one or more times, passing a fragment of the message each time. + The signature that is calculated is the signature of the concatenation of these messages in order. + #. To extract the signature the hash, call `psa_sign_finish()`. + + After a successful call to `psa_sign_setup()`, the operation is active, and the application must eventually terminate the operation. + The following events terminate an operation: + + * A successful call to `psa_sign_finish()`. + * A call to `psa_sign_abort()`. + + If `psa_sign_setup()` returns an error, the operation object is unchanged. + If a subsequent function call with an active operation returns an error, the operation enters an error state. + + To abandon an active operation, or reset an operation in an error state, call `psa_sign_abort()`. + + See :secref:`multi-part-operations`. + +.. function:: psa_sign_update + + .. summary:: + Add a message fragment to a multi-part sign operation. + + .. versionadded:: 1.5 + + .. param:: psa_sign_operation_t * operation + Active sign operation. + .. param:: const uint8_t * input + Buffer containing the message fragment to sign. + .. param:: size_t input_length + Size of the ``input`` buffer in bytes. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be active. + * The library requires initializing by a call to `psa_crypto_init()`. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The total input for the operation is too large for the signature algorithm. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The total input for the operation is too large for the implementation. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + + The application must call `psa_sign_setup()` before calling this function. + + When the last fragment of the message has been input to the multi-part sign operation, call `psa_sign_finish()` to calculate and extract the signature. + + If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_sign_abort()`. + +.. function:: psa_sign_finish + + .. summary:: + Finish the calculation of an asymmetric signature of a message. + + .. versionadded:: 1.5 + + .. param:: psa_sign_operation_t * operation + Active sign operation. + .. param:: uint8_t * signature + Buffer where the signature is to be written. + .. param:: size_t signature_size + Size of the ``signature`` buffer in bytes. + This must be appropriate for the selected algorithm and key: + + * The required signature size is :code:`PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg)` where ``key_type`` and ``key_bits`` are the type and bit-size of the key, and ``alg`` is the algorithm that were used in the call to `psa_sign_setup()`. + * `PSA_SIGNATURE_MAX_SIZE` evaluates to the maximum signature size of any supported signature algorithm. + .. param:: size_t * signature_length + On success, the number of bytes that make up the returned signature value. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*signature_length)`` bytes of ``signature`` contain the signature value. + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be active. + * The library requires initializing by a call to `psa_crypto_init()`. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``signature`` buffer is too small. + `PSA_SIGN_OUTPUT_SIZE()` or `PSA_SIGNATURE_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + + The application must call `psa_sign_setup()` before calling this function. + This function calculates the asymmetric signature of the message formed by concatenating the inputs passed to preceding calls to `psa_sign_update()`. + + When this function returns successfully, the operation becomes inactive. + If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_sign_abort()`. + +.. function:: psa_sign_abort + + .. summary:: + Abort a sign operation. + + .. versionadded:: 1.5 + + .. param:: psa_sign_operation_t * operation + Initialized sign operation. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The operation object can now be discarded or reused. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Aborting an operation frees all associated resources except for the ``operation`` object itself. Once aborted, the operation object can be reused for another operation by calling `psa_sign_setup()` again. + + This function can be called any time after the operation object has been initialized by one of the methods described in `psa_sign_operation_t`. + + In particular, calling `psa_sign_abort()` after the operation has been terminated by a call to `psa_sign_abort()` or `psa_sign_finish()` is safe and has no effect. + +.. typedef:: /* implementation-defined type */ psa_verify_operation_t + + .. summary:: + The type of the state object for multi-part asymmetric signature verification operations. + + .. versionadded:: 1.5 + + Before calling any function on a verify operation object, the application must initialize it by any of the following means: + + * Set the object to all-bits-zero, for example: + + .. code-block:: xref + + psa_verify_operation_t operation; + memset(&operation, 0, sizeof(operation)); + + * Initialize the object to logical zero values by declaring the object as static or global without an explicit initializer, for example: + + .. code-block:: xref + + static psa_verify_operation_t operation; + + * Initialize the object to the initializer `PSA_VERIFY_OPERATION_INIT`, for example: + + .. code-block:: xref + + psa_verify_operation_t operation = PSA_VERIFY_OPERATION_INIT; + + * Assign the result of the function `psa_verify_operation_init()` to the object, for example: + + .. code-block:: xref + + psa_verify_operation_t operation; + operation = psa_verify_operation_init(); + + This is an implementation-defined type. + Applications that make assumptions about the content of this object will result in implementation-specific behavior, and are non-portable. + +.. macro:: PSA_VERIFY_OPERATION_INIT + :definition: /* implementation-defined value */ + + .. summary:: + This macro returns a suitable initializer for a verify operation object of type `psa_verify_operation_t`. + + .. versionadded:: 1.5 + +.. function:: psa_verify_operation_init + + .. summary:: + Return an initial value for a verify operation object. + + .. versionadded:: 1.5 + + .. return:: psa_verify_operation_t + +.. function:: psa_verify_setup + + .. summary:: + Set up a multi-part verify operation. + + .. versionadded:: 1.5 + + .. param:: psa_verify_operation_t * operation + The operation object to set up. + It must have been initialized as per the documentation for `psa_verify_operation_t` and not yet in use. + .. param:: psa_key_id_t key + Identifier of the key to use for the operation. + It must be a public key or an asymmetric key pair. + It must remain valid until the operation terminates. + The key must permit the usage `PSA_KEY_USAGE_VERIFY_MESSAGE`. + .. param:: psa_algorithm_t alg + An asymmetric signature algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_SIGN_MESSAGE(alg)` is true. + .. param:: const uint8_t * context + The context to use for this signature. + .. param:: size_t context_length + Size of the ``context`` buffer in bytes. + .. param:: const uint8_t * signature + Buffer containing the signature to verify. + .. param:: size_t signature_length + Size of the ``signature`` buffer in bytes. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The operation is now active. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The key does not have the `PSA_KEY_USAGE_VERIFY_MESSAGE` flag, or it does not permit the requested algorithm. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported, or is not an asymmetric signature algorithm that permits verifying a message. + * ``key`` is not supported for use with ``alg``. + * The implementation does not support this value of ``context_length`` for ``alg``. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not an asymmetric signature algorithm that permits verifying a message with a non-zero-length context. + * ``key`` is not a public key or an asymmetric key pair, that is compatible with ``alg``. + * ``context_length`` is not valid for the algorithm and key type. + * ``context`` is not a valid input value for the algorithm and key type. + .. 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_INSUFFICIENT_ENTROPY + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be inactive. + * The library requires initializing by a call to `psa_crypto_init()`. + + If a context parameter is not required or not supported by the algorithm, a zero-length context must be provided. + + The sequence of operations to verify a message signature is as follows: + + 1. Allocate a verify operation object which will be passed to all the functions listed here. + #. Initialize the operation object with one of the methods described in the documentation for `psa_verify_operation_t`, for example `PSA_VERIFY_OPERATION_INIT`. + #. Call `psa_verify_setup()` to specify the key-pair, algorithm, context value, and signature to verify. + #. Call `psa_verify_update()` zero, one or more times, passing a fragment of the message each time. + The signature tis verified against the concatenation of these messages in order. + #. To determine the validity of the signature, call `psa_verify_finish()`. + + After a successful call to `psa_verify_setup()`, the operation is active, and the application must eventually terminate the operation. + The following events terminate an operation: + + * A successful call to `psa_verify_finish()`. + * A call to `psa_verify_abort()`. + + If `psa_verify_setup()` returns an error, the operation object is unchanged. + If a subsequent function call with an active operation returns an error, the operation enters an error state. + + To abandon an active operation, or reset an operation in an error state, call `psa_verify_abort()`. + + See :secref:`multi-part-operations`. + +.. function:: psa_verify_update + + .. summary:: + Add a message fragment to a multi-part verify operation. + + .. versionadded:: 1.5 + + .. param:: psa_verify_operation_t * operation + Active verify operation. + .. param:: const uint8_t * input + Buffer containing the message fragment to verify. + .. param:: size_t input_length + Size of the ``input`` buffer in bytes. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be active. + * The library requires initializing by a call to `psa_crypto_init()`. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The total input for the operation is too large for the signature algorithm. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The total input for the operation is too large for the implementation. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + + The application must call `psa_verify_setup()` before calling this function. + + When the last fragment of the message has been input to the multi-part verify operation, call `psa_verify_finish()` to determine the validity of the signature. + + If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_verify_abort()`. + +.. function:: psa_verify_finish + + .. summary:: + Report the validity of the message signature. + + .. versionadded:: 1.5 + + .. param:: psa_verify_operation_t * operation + Active verify operation. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The signature is valid. + .. retval:: PSA_ERROR_INVALID_SIGNATURE + The signature being verified by the operation is not the result of signing the concatenated message with the operation's algorithm using the private key corresponding to the operation's key. + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be active. + * The library requires initializing by a call to `psa_crypto_init()`. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + + The application must call `psa_verify_setup()` before calling this function. + This function verifies the asymmetric signature with the message formed by concatenating the inputs passed to preceding calls to `psa_verify_update()`. + + When this function returns successfully, the operation becomes inactive. + If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_verify_abort()`. + +.. function:: psa_verify_abort + + .. summary:: + Abort a verify operation. + + .. versionadded:: 1.5 + + .. param:: psa_verify_operation_t * operation + Initialized verify operation. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The operation object can now be discarded or reused. + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Aborting an operation frees all associated resources except for the ``operation`` object itself. Once aborted, the operation object can be reused for another operation by calling `psa_verify_setup()` again. + + This function can be called any time after the operation object has been initialized by one of the methods described in `psa_verify_operation_t`. + + In particular, calling `psa_verify_abort()` after the operation has been terminated by a call to `psa_verify_abort()` or `psa_verify_finish()` is safe and has no effect. + Support macros -------------- diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 1a79ea5c..6fe19ca5 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -17,6 +17,9 @@ Changes between *1.4.1* and *1.5.0* Changes to the API ~~~~~~~~~~~~~~~~~~ +* Provide multi-part operations for asymmetric signatures. + This enables many message-signature algorithms to be used for fragmented messages. + See :secref:`multi-part-signature`. Relaxations ~~~~~~~~~~~ diff --git a/doc/crypto/overview/functionality.rst b/doc/crypto/overview/functionality.rst index 1403dce6..482190b6 100644 --- a/doc/crypto/overview/functionality.rst +++ b/doc/crypto/overview/functionality.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2018-2025 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2018-2026 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. _functionality-overview: @@ -277,7 +277,7 @@ This specification defines interfaces for the following types of asymmetric cryp * Key encapsulation. See :secref:`key-encapsulation`. * Password-authenticated key exchange (PAKE). See :secref:`pake`. -For asymmetric signature, the API provides *single-part* functions. +For asymmetric signature, the API provides *single-part* functions and *multi-part* operations. For asymmetric encryption, the API provides single-part functions. @@ -285,7 +285,7 @@ For key agreement, the API provides single-part functions and an additional inpu For key encapsulation, the API provides single-part functions. -For PAKE, the API provides a *multi-part* operation. +For PAKE, the API provides a multi-part operation. Randomness and key generation