Skip to content

Add interruptible Crypto API operations - #375

Merged
athoelke merged 31 commits into
GlobalPlatform:mainfrom
athoelke:crypto-interruptible-v1.6
Sep 17, 2026
Merged

athoelke merged 31 commits into
GlobalPlatform:mainfrom
athoelke:crypto-interruptible-v1.6

Conversation

@athoelke

@athoelke athoelke commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

This is a rebased version of #107 and #199, targetting version 1.6 of the specification.

Apart from adding the previously drafted APIs, this incorporates other changes to the documentation since the original PRs. The introductory text for interruptible signatures has also been updated to reflect the presence of both multi-part signatures and interruptibel signature APIs.

@athoelke athoelke added this to the Crypto API 1.x milestone Jul 24, 2026
@athoelke athoelke self-assigned this Jul 24, 2026
@athoelke athoelke added enhancement New feature or request API design Related the design of the API Crypto API Issue or PR related to the Cryptography API labels Jul 24, 2026

@gilles-peskine-arm gilles-peskine-arm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've reviewed the document with the partial implementation in TF-PSA-Crypto in mind. We know that we'll need to update our implementation since it followed a now outdated beta.

Many of my comments apply to multiple operation types. I only noted the first place where I noticed something.

My biggest concern is the verify flow. For verify-message, I don't think providing the signature before the message works out in practice.

Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/ops/signature.rst Outdated
Comment thread doc/crypto/figure/interruptible_operation_complex.puml
Comment thread doc/crypto/api.db/psa/crypto.h
Comment thread doc/crypto/overview/functionality.rst Outdated
Comment thread doc/crypto/overview/functionality.rst
@athoelke

athoelke commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

My biggest concern is the verify flow. For verify-message, I don't think providing the signature before the message works out in practice.

Quick response on this:

  1. such an observation also affects the already defined verify-message multi-part operation.
  2. Deferring the signature is not possible for PureEdDSA, SLH-DSA, LMS/HSS, or XMSS - although it is for ECDSA, RSA-*, HashEdDSA, HashSLH-DSA and all forms of ML-DSA.

A algorithm-agnostic flow requires the signature before the message parts.

@athoelke

athoelke commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Following discussion - we need to support use cases where the signature is only provided after the message content (required for some streaming protocols), as well as use cases where the signature is provided before the message (which is required for some algorithms).

For psa_verify_iop_t, the proposal is to enable a 'late signature' flow, that is only available for some algorithms, and a general 'early signature' flow that works for any algorithm.

Using the current psa_verify_iop_setup() function signals the use of the general/early-signature flow, and the rest of the API should be used as currently described.

For the new flow, three additional APIs are provided:

psa_status_t psa_verify_iop_setup_deferred_signature(...);
psa_status_t psa_verify_iop_set_signature(...);
#define PSA_ALG_SIGN_SUPPORTS_DEFERRED_SIGNATURE(alg) ...
  • psa_verify_iop_setup_deferred_signature() acts like the current setup function, but without the signature. This indicates that the application will only provide the signature after the message/hash input immediately before completion. If the algorithm or implementation does not support that flow, this is reported as an error response to this function call.
  • psa_verify_iop_set_signature() supplies the signature to an interruptible verify operation, after all the message/hash input has been provided, and before any call to psa_verify_iop_complete(). If called when a signature has already been provided, this returns BAD_STATE.
  • If no signature has been provided (either in setup or via psa_verify_iop_set_signature()), then psa_verify_iop_complete() returns BAD_STATE.
  • PSA_ALG_SIGN_SUPPORTS_DEFERRED_SIGNATURE() reports whether or not a signature algorithm enables a late-signature flow. This is independent of implememtation-specific support for late flows.

This design, providing a distinct setup function, enables the implementation to detect the application intent explicitly and immediately, and respond with an error if not supported. With a more generic, single setup function without a signature; the application intent can only be inferred when psa_verify_iop_setup_complete() is called before providing a signature.

@athoelke

Copy link
Copy Markdown
Collaborator Author

I think I've managed to address all of the substanive issues raised in the feedback so far. I would appreciate a re-review of the resulting updated PR.

@gilles-peskine-arm gilles-peskine-arm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the updates. I only have a couple of minor nits now, except maybe for one point. I want to think further about verification with and without deferred signature.

Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/ops/signature.rst Outdated
Comment thread doc/crypto/api/keys/management.rst Outdated
Comment thread doc/crypto/api/keys/management.rst
Comment thread doc/crypto/overview/functionality.rst
@athoelke

Copy link
Copy Markdown
Collaborator Author

I had another thought about the verification and deferred signatures.

For both the multi-part and interruptible verification operations, the operation object wil have to copy some or all of the signature data if it is passed during setup. For PQC signatures, this can be a very sizeable buffer and will be challenging for constrained implementations with no dynamic allocation.

However, although it might work (from a memory management point of view) to have the application deal with the signature memory issue, and pass the signature to both the setup and the finishing phases for an algorithm that requires the signature before the message - is there a security/cryptographic risk in having the application pass what is meant to be the same signature data twice to the implementation?

@gilles-peskine-arm

Copy link
Copy Markdown
Contributor

For both the multi-part and interruptible verification operations, the operation object wil have to copy some or all of the signature data if it is passed during setup.

I think that for interruptible operations, this memory has to exist anyway between start() and the last complete() of the finish phase. So it has to be stored in the operation object at some point, directly or indirectly. So for interruptible operations, I think that passing the signature separately will always work.

For multipart operations, it's a different matter: with most algorithms, the signature only needs to exist during the verify-finish phase, which is a single function call.

is there a security/cryptographic risk in having the application pass what is meant to be the same signature data twice to the implementation?

It's definitely more error prone. I can't think of a direct security risk however, since the inputs of verification are generally not confidential and the output is a single boolean. If the application makes a mistake and passes a different signature, the worst that can happen is that it will get a passing verification without a correct signature. But the application is only harming itself. The surface against glitch attacks is likely much higher, though.

@athoelke

Copy link
Copy Markdown
Collaborator Author

Another inconsistency has come to light after implementing #381.

The behaviour of the interruptible operation functions when the operation is not in a valid state for the chosen algorithm is to report a PSA_ERROR_INVALID_ARGUMENT error (for example trying to update a sign iop with two message fragments, when the algorithm requires that the entire message is provided in a single fragment, or trying to sign a pre-computed hash with an algorithm that can only sign messages).

These are scenarios where the function being called is incorrect for the operation state (including algorithm-specific state) irrespective of the arguments passed to the function. In other multi-part operations, similar scenarios result in a PSA_ERROR_BAD_STATE response. For example:

  • If an IV is generated or set for a cipher algorithm that does not have an IV
  • If a nonce is generated or set before calling psa_aead_set_lengths() for an AEAD algorithm that requires the lengths to be explicitly set.
  • If a KDF input step is provided out of sequence, or illegally repeated for the chosen algorithm.

I suspect the behaviour (using PSA_ERROR_INVALID_ARGUMENT) in the current PR was influenced by the more recent decision on how to handle contexts for signature operations. These do use PSA_ERROR_INVALID_ARGUMENT, and implement a default when no context is provided for an algorithm defined to take one - but the justification for this is that not all algorithms define a context, nearly all protocols do not use a context, and there is an obvious default that is defined to work as required in algorithms that take them.

There are some scenarios in the new interruptible operations (and possibly in the multi-part sign/verify operations?) which might be better served by using PSA_ERROR_BAD_STATE to report that the API being called is not appropriate for the current operation?

@athoelke

Copy link
Copy Markdown
Collaborator Author

Another unusual aspect to the sign and verify iop API is that the permission check for the keys is deferred until the application calls the hash(), update(), or complete() functions. This is because we have distinct usage policies for signing (or verifying) hashes and messages. Every other operation checks the key policy at the time the key is provided to the operation.

This is not ideal, both from an application error discovery point of view, or from an implementation point of view (which often combines key lookup with policy verification).

I propose to check for the appropriate SIGN_MESSAGE/VERIFY_MESSAGE usage when the operation is set up - noting that SIGN_HASH usage always implies SIGN_MESSAGE permission as well. Then there is a second permission check if the applicaiton uses the hash() function to sign or verify a pre-computed hash, to ensure that the key had the stronger SIGN_HASH/VERIFY_HASH permission. As a result, the permission checks on update(), set_signature() or complete() are no longer needed.

Although this still defers part of the permission check in some uses, it provides a better compromise without introducing separate setup APIs for hash and message interruptible signature operations.

@athoelke

Copy link
Copy Markdown
Collaborator Author

I have added a few more commits to regularise the following:

  • Signatures that are invalid are now only reported when completing the interruptible verification, using PSA_ERROR_INVALID_SIGNATURE - as is done in other signature verification functions and operations.
  • Interruptible operation function calls that are not valid for the operation state (including the selected algorithm) are now PSA_ERROR_BAD_STATE errors.
  • Key usage policy verification for signature and verification is clarified: the only deferred usage check is when using a pre-computed hash in the new operations. This approach is based on the behaviour of the message and hash signing/verifying usage policies: e.g. a key with PSA_KEY_USAGE_SIGN_HASH automatically also has PSA_KEY_USAGE_SIGN_MESSAGE.

@gilles-peskine-arm gilles-peskine-arm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Mostly LGTM, but there are still a few kinks in the verify flow.

Comment thread doc/crypto/api/ops/signature.rst
Comment thread doc/crypto/api/ops/signature.rst Outdated
Comment thread doc/crypto/api/ops/signature.rst

@gilles-peskine-arm gilles-peskine-arm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM for the overall design.

I've done a detailed review of most of the content, but I haven't verified that the last commit 84ad096 is complete.

Signed-off-by: Andrew Thoelke <andrew.thoelke@arm.com>
Signed-off-by: Andrew Thoelke <andrew.thoelke@arm.com>
@athoelke
athoelke force-pushed the crypto-interruptible-v1.6 branch from f1fa64f to 8cdff16 Compare September 9, 2026 14:48
@athoelke

athoelke commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased to resolve conflict in history.rst with upstream main branch.

@athoelke
athoelke merged commit ad3ad95 into GlobalPlatform:main Sep 17, 2026
@athoelke
athoelke deleted the crypto-interruptible-v1.6 branch September 17, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API design Related the design of the API Crypto API Issue or PR related to the Cryptography API enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for interruptible key agreement/exchange Interruptible/bounded-latency asymmetric operations

2 participants