Skip to content

Commit

Permalink
crypto: Add interruptible asymmetric signature API
Browse files Browse the repository at this point in the history
Provide interruptible operations for message and hash signature calculation and verification.

Reworked information in this section of the API relating to the behavior of different types of signature algorithm, consolidating this to the section introduction.
  • Loading branch information
athoelke committed Oct 12, 2023
1 parent d3949f0 commit acd80e3
Show file tree
Hide file tree
Showing 8 changed files with 944 additions and 112 deletions.
42 changes: 42 additions & 0 deletions doc/crypto/api.db/psa/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ typedef uint8_t psa_key_persistence_t;
typedef uint16_t psa_key_type_t;
typedef uint32_t psa_key_usage_t;
typedef /* implementation-defined type */ psa_mac_operation_t;
typedef /* implementation-defined type */ psa_sign_interruptible_operation_t;
typedef /* implementation-defined type */ psa_verify_interruptible_operation_t;
#define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \
/* implementation-defined value */
#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \
Expand Down Expand Up @@ -207,6 +209,7 @@ typedef /* implementation-defined type */ psa_mac_operation_t;
/* specification-defined value */
#define PSA_HASH_SUSPEND_OUTPUT_MAX_SIZE /* implementation-defined value */
#define PSA_HASH_SUSPEND_OUTPUT_SIZE(alg) /* specification-defined value */
#define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX
#define PSA_KEY_ATTRIBUTES_INIT /* implementation-defined value */
#define PSA_KEY_DERIVATION_INPUT_CONTEXT /* implementation-defined value */
#define PSA_KEY_DERIVATION_INPUT_COST /* implementation-defined value */
Expand Down Expand Up @@ -298,9 +301,13 @@ typedef /* implementation-defined type */ psa_mac_operation_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_INTERRUPTIBLE_OPERATION_INIT \
/* implementation-defined value */
#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \
/* implementation-defined value */
#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE /* implementation-defined value */
#define PSA_VERIFY_INTERRUPTIBLE_OPERATION_INIT \
/* implementation-defined value */
psa_status_t psa_aead_abort(psa_aead_operation_t * operation);
psa_status_t psa_aead_decrypt(psa_key_id_t key,
psa_algorithm_t alg,
Expand Down Expand Up @@ -483,6 +490,8 @@ psa_status_t psa_import_key(const psa_key_attributes_t * attributes,
const uint8_t * data,
size_t data_length,
psa_key_id_t * key);
uint32_t psa_interruptible_get_max_ops(void);
void psa_interruptible_set_max_ops(uint32_t max_ops);
psa_key_attributes_t psa_key_attributes_init(void);
psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t * operation);
psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t * operation,
Expand Down Expand Up @@ -577,6 +586,23 @@ psa_status_t psa_sign_hash(psa_key_id_t key,
uint8_t * signature,
size_t signature_size,
size_t * signature_length);
psa_status_t psa_sign_interruptible_abort(psa_sign_interruptible_operation_t * operation);
psa_status_t psa_sign_interruptible_complete(psa_sign_interruptible_operation_t * operation,
uint8_t * signature,
size_t signature_size,
size_t * signature_length);
uint32_t psa_sign_interruptible_get_num_ops(psa_sign_interruptible_operation_t * operation);
psa_status_t psa_sign_interruptible_hash(psa_sign_interruptible_operation_t * operation,
const uint8_t * hash,
size_t hash_length);
psa_sign_interruptible_operation_t psa_sign_interruptible_operation_init(void);
psa_status_t psa_sign_interruptible_setup(psa_sign_interruptible_operation_t * operation,
psa_key_id_t key,
psa_algorithm_t alg);
psa_status_t psa_sign_interruptible_setup_complete(psa_sign_interruptible_operation_t * operation);
psa_status_t psa_sign_interruptible_update(psa_sign_interruptible_operation_t * operation,
const uint8_t * input,
size_t input_length);
psa_status_t psa_sign_message(psa_key_id_t key,
psa_algorithm_t alg,
const uint8_t * input,
Expand All @@ -590,6 +616,22 @@ psa_status_t psa_verify_hash(psa_key_id_t key,
size_t hash_length,
const uint8_t * signature,
size_t signature_length);
psa_status_t psa_verify_interruptible_abort(psa_verify_interruptible_operation_t * operation);
psa_status_t psa_verify_interruptible_complete(psa_verify_interruptible_operation_t * operation);
uint32_t psa_verify_interruptible_get_num_ops(psa_verify_interruptible_operation_t * operation);
psa_status_t psa_verify_interruptible_hash(psa_verify_interruptible_operation_t * operation,
const uint8_t * hash,
size_t hash_length);
psa_verify_interruptible_operation_t psa_verify_interruptible_operation_init(void);
psa_status_t psa_verify_interruptible_setup(psa_verify_interruptible_operation_t * operation,
psa_key_id_t key,
psa_algorithm_t alg,
const uint8_t * signature,
size_t signature_length);
psa_status_t psa_verify_interruptible_setup_complete(psa_verify_interruptible_operation_t * operation);
psa_status_t psa_verify_interruptible_update(psa_verify_interruptible_operation_t * operation,
const uint8_t * input,
size_t input_length);
psa_status_t psa_verify_message(psa_key_id_t key,
psa_algorithm_t alg,
const uint8_t * input,
Expand Down
54 changes: 53 additions & 1 deletion doc/crypto/api/library/library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
:include: psa/error.h

/* This file is a reference template for implementation of the
* PSA Certified Crypto API v1.1
* PSA Certified Crypto API v1.2
*/

Expand Down Expand Up @@ -73,3 +73,55 @@ Library initialization

.. warning::
The set of functions that depend on successful initialization of the library is :scterm:`IMPLEMENTATION DEFINED`. Applications that rely on calling functions before initializing the library might not be portable to other implementations.


Interruptible operation limit
-----------------------------

.. todo:: Provide simple intro to these support functions

See :secref:`interruptible-operations`

.. function:: psa_interruptible_set_max_ops

.. summary::
Set the maximum number of *ops* allowed to be executed by an interruptible function in a single call.

.. param:: uint32_t max_ops
The maximum number of ops to be executed in a single call, this can be a number from ``0`` to `PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED`, where ``0`` is obviously the least amount of work done per call.

.. return:: void

Interruptible functions use this value to limit the computation that is done in any single call to the function. If this limit is reached, the function will return :code:`PSA_OPERATION_INCOMPLETE`, and the caller must repeat the function call until a different status code is returned, or abort the operation.

After initialization of the implementation, the maximum *ops* defaults to `PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED`. This means that the whole operation will complete in a single call, regardless of the number of *ops* required. An application must call `psa_interruptible_set_max_ops()` to set a different limit.

.. note::

The time taken to execute a single *op* is implementation specific and depends on software, hardware, the algorithm, key type and curve chosen. Even within a single operation, successive ops can take differing amounts of time. The only guarantee is that lower values for ``max_ops`` means functions will block for a lesser maximum amount of time and conversely larger values will mean blocking for a larger maximum amount of time. The functions `psa_sign_interruptible_get_num_ops()` and `psa_verify_interruptible_get_num_ops()` are provided to help with tuning this value.

.. admonition:: Implementation note

The interpretation of this maximum number is obviously also implementation defined. On a hard real-time system, this can indicate a hard deadline, which is good, as a real-time system needs a guarantee of not spending more than X time, however care must be taken to avoid the situation whereby calls just return, not being able to do any actual work within the allotted time. On a non-real-time system, the implementation can be more relaxed, but again whether this number should be interpreted as as hard or soft limit or even whether a less than or equals as regards to ops executed in a single call is implementation defined.

.. warning::
With implementations that interpret this number as a hard limit, setting this number too small can result in an infinite loop, whereby each call results in immediate return with no computation done.

.. function:: psa_interruptible_get_max_ops

.. summary::
Get the maximum number of *ops* allowed to be executed by an interruptible function in a single call.

.. return:: uint32_t
Maximum number of *ops* allowed to be executed by an interruptible function in a single call.

This returns the value last set in a call to `psa_interruptible_set_max_ops()`.

.. macro:: PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED
:definition: UINT32_MAX

.. summary::

Maximum value for use with `psa_interruptible_set_max_ops()`.

Using this value in a call to `psa_interruptible_set_max_ops()` will cause interruptible functions to complete their calculation before returning.
Loading

0 comments on commit acd80e3

Please sign in to comment.