Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for interruptible key agreement/exchange #198

Open
athoelke opened this issue May 14, 2024 · 8 comments · May be fixed by #199
Open

Support for interruptible key agreement/exchange #198

athoelke opened this issue May 14, 2024 · 8 comments · May be fixed by #199
Labels
API design Related the design of the API Crypto API Issue or PR related to the Cryptography API enhancement New feature or request

Comments

@athoelke
Copy link
Contributor

Issue #23 considers interruptible API design, and specifically looks at an API for asymmetric signature. There is a PR for an interruptible API for asymmetric signature creation and verification in #107.

Another use case that requires an interruptible operation is key agreement, in particular ECDH. (See Mbed-TLS/mbedtls#9044)

For ECDH, the complex computation occurs at the following points:

  1. Computing the public key from an ECC private key.
  2. Validation of the public key provided by the other participant.
  3. Computing the shared secret from the two input keys.

In the current PSA Crypto API, steps (2) and (3) occur as part of the key agreement function. Step (1) might occur during key generation, or during public key export, depending on the implementation's approach to storing ECC keys.

For full coverage of the key agreement use case we would need interruptible operations for all three APIs (key generation, key export, and key agreement).

As each of these functions have simple (bounded) inputs, the interruptible operations can be much simpler that the one designed for asymmetric signature. In particular, each operation only requires a single setup function taking all the inputs (called once) and a single completion function providing the outputs (called until finished).

@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 May 14, 2024
@athoelke athoelke added this to the Crypto API 1.x milestone May 14, 2024
@athoelke
Copy link
Contributor Author

athoelke commented May 15, 2024

Following the patterns in #107, the obvious pattern for these interruptible operations would be something like the following:

typedef /* implementation-defined */ psa_generate_key_interruptible_operation_t;
#define PSA_GENERATE_KEY_INTERRUPTIBLE_OPERATION_INIT /* implementation-defined */
psa_generate_key_interruptible_operation_t psa_generate_key_interruptible_operation_init();

psa_status_t psa_generate_key_interruptible_setup(psa_generate_key_interruptible_operation_t *op,
                                                  const psa_key_attributes_t * attr);
psa_status_t psa_generate_key_interruptible_complete(psa_generate_key_interruptible_operation_t *op,
                                                     psa_key_id_t *key);
psa_status_t psa_generate_key_interruptible_abort(psa_generate_key_interruptible_operation_t *op);

One concern I have is that these names are getting rather long (and psa_export_public_key_interruptible_operation_t gets longer). As psa_generate_key_interruptible_ is already 31 characters, all of the identifiers are indistinguishable in the first 31 characters: and thus a C99 implementation is not required to distinguish these identifiers.

Key Question

Do we need to devise a shorter format for naming these type of operations and their functions, so that code remains both readable and unambiguous?

And if we do, we should retro-fit the same pattern to #23 & #107.

I'll propose a strawman idea, to provoke a reaction... how about using intop in the structure and function names to indicate that this is part of an interruptible operation? - it isn't a valid abbreviation for anything, so would not be misunderstood even if unknown to a reader... i.e. psa_generate_key_intop_t and psa_generate_key_intop_setup(), etc.

Note that to achieve disambiguation in 31 characters for public key export, we need a suffix that is 7 characters or less as psa_export_public_key_1234567_ is 30 characters long.

@athoelke
Copy link
Contributor Author

Perhaps, given that these functions will not require multi-part operations, we could elide the 'interruptible' entirely in the identifier names? - the use of the interruptible form of the API would still be evident in the code from the use of xxx_setup(), xxx_complete() and PSA_OPERATION_INCOMPLETE. i.e.

typedef /* implementation-defined */ psa_generate_key_operation_t;
#define PSA_GENERATE_KEY_OPERATION_INIT /* implementation-defined */
psa_generate_key_operation_t psa_generate_key_operation_init();

psa_status_t psa_generate_key_setup(psa_generate_key_operation_t *op,
                                    const psa_key_attributes_t * attr);
psa_status_t psa_generate_key_complete(psa_generate_key_operation_t *op,
                                       psa_key_id_t *key);
psa_status_t psa_generate_key_abort(psa_generate_key_operation_t *op);

@athoelke
Copy link
Contributor Author

Maybe _start() is better than _setup() to distinguish from multi-part operations? - the challenge is the two-phases of completion for the interruptible signature API (see #98).

@athoelke
Copy link
Contributor Author

See the discussion of API naming options in #98, which concluded with the following proposal for key generation and key agreement:

/* Key Generation ---------------------------------------*/

typedef /* implementation-defined */ psa_generate_key_iop_t;

#define PSA_GENERATE_KEY_IOP_INIT /* implementation-defined */

psa_generate_key_iop_t psa_generate_key_iop_init();

psa_status_t psa_generate_key_iop_setup(psa_generate_key_iop_t *iop,
                                        const psa_key_attributes_t * attr);
psa_status_t psa_generate_key_iop_complete(psa_generate_key_iop_t *iop,
                                           psa_key_id_t *key);
psa_status_t psa_generate_key_iop_abort(psa_generate_key_iop_t *iop);

/* Key Agreement ----------------------------------------*/

typedef /* implementation-defined */ psa_key_agreement_iop_t;

#define PSA_GENERATE_KEY_IOP_INIT /* implementation-defined */

psa_generate_key_iop_t psa_key_agreement_iop_init();

psa_status_t psa_key_agreement_iop_setup(psa_key_agreement_iop_t *iop,
                                         const psa_key_attributes_t *attr,
                                         psa_key_id_t private_key,
                                         const uint8_t *peer_key,
                                         size_t peer_key_length);
psa_status_t psa_key_agrement_iop_complete(psa_key_agreement_iop_t *iop,
                                           psa_key_id_t *key);
psa_status_t psa_key_agreement_iop_abort(psa_key_agreement_iop_t *iop);

The extension to this pattern for public key export would be:

/* Public key export ----------------------------------------*/

typedef /* implementation-defined */ psa_export_public_key_iop_t;

#define PSA_EXPORT_PUBLIC_KEY_IOP_INIT /* implementation-defined */

psa_export_public_key_iop_t psa_export_public_key_iop_init();

psa_status_t psa_export_public_key_iop_setup(psa_export_public_key_iop_t *iop,
                                             psa_key_id_t key);
psa_status_t psa_export_public_key_iop_complete(psa_export_public_key_iop_t *iop,
                                                uint8_t * data,
                                                size_t data_size,
                                                size_t * data_length);
psa_status_t psa_export_public_key_iop_abort(psa_export_public_key_iop_t *iop);

@athoelke
Copy link
Contributor Author

In light of #194, should the interruptible key generation support additional production parameters, or only the default production parameters?

@athoelke
Copy link
Contributor Author

Similarly, in light of #149, should an interruptible public key export operation support alternative output formats?

@gilles-peskine-arm
Copy link
Contributor

We should have a way to have both custom production parameters and interruptibility. We aren't actually going to implement those variants in Mbed TLS since we only do custom production parameters for RSA and we only do interruptibility for ECC. But if someone needs them, they should exist in the API design so that implementers and users agree on naming, order of parameters, etc.

@athoelke
Copy link
Contributor Author

In light of #194, should the interruptible key generation support additional production parameters, or only the default production parameters?

Similarly, in light of #149, should an interruptible public key export operation support alternative output formats?

The current opinion is that the default API should just cater for the default use cases (standard key generation/key format), and we can add additional setup or completion functions for interruptible operations that do need extended behavior. This also avoids trying to pre-empt a decision on API naming for things such as formatted key export.

@athoelke athoelke linked a pull request Jun 20, 2024 that will close this issue
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
Development

Successfully merging a pull request may close this issue.

2 participants