Skip to content

Crypto driver interface for multipart sign-message and verify-message #350

@gilles-peskine-arm

Description

@gilles-peskine-arm

We are adding multi-part sign-message and verify-message to the crypto API. So we need to add them to the driver interface as well.

The general principle for the driver interface is to pass attributes, key_buffer, key_buffer_size to functions where the API passes a key identifier. If we follow this principle, then a driver receives the key material in its "sign_setup" and "verify_setup" entry points. It's then up to the driver to store the key material until the key is used in the "sign_finish" and "verify_finish" entry points, since those entry points do not receive the key material as input.

For multipart symmetric operations and ECC-based operations, this is fine, because the key material uses a negligible amount of memory. (For key derivation, the memory for temporary storage can be a concern for some inputs, but since the inputs aren't in the key store, the data management is fundamentally different.) But with most post-quantum algorithms, for example ML-DSA, that means a large amount of key material to be stored in the operation object.

Consider for example an ML-DSA as implemented in Mbed-TLS/TF-PSA-Crypto#770, where the core stores the key in its standard export format:

  • The "sign_setup" entry point derives the expanded private key and the public key from the seed. It uses the public key immediately, and stores a copy of the expanded private key (4.8 kB) in the operation. (It could store just the seed, but that would require deriving the private key again during "sign_finish", which has a non-negligible cost in processing time.)
  • The "verify_setup" entry point both uses the public key immediately, and stores a copy (2.6 kB) in the operation object which is used during "verify_finish".

The API guarantees that when a multi-part operation is using a key, the key exists in the key store, since psa_destroy_key must interrupt operations using the key that is being destroyed. (The key does not need to exist in RAM, especially if it's persistent, but that's an implementation choice.)

Thus, instead of requiring each operation to keep a copy of the key, multipart sign-message and verify-message should allow the driver to access the information that's already in the core.

In the case of verfiy-message for ML-DSA, the preferred behavior is simple: the setup phase requires the key in the standard representation, and the finish phase requires the key in the driver's preferred expanded representation (if that differs).

In the case of sign-message for ML-DSA, the preferred behavior is more complicated. The setup phase requires the public key (which needs to be derived from the standard representation of the key-pair, which is the seed). The finish phase requires the expanded private key (in the driver's preferred representation). For a core that only stores the standard representation, combined with a driver that calculates the expanded private key and the public key at the same time, passing the key again to the "sign_finish" entry point allows the driver to choose between optimizing for performance and memory usage. For a core that stores the fully expanded form of the key in persistent storage, passing that expanded form to both "sign_setup" and "finish_setup" allows a significant memory saving.

It's not fully clear to me how much the ML-DSA situation is generalizable to all sign-message algorithms, or how to cope with cores and drivers having different preferences about the key representation in memory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    API designRelated the design of the APICrypto APIIssue or PR related to the Cryptography APIenhancementNew feature or request

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions