Hi Gilles
Thanks for the quick response.
See my answers below.
Von: Gilles Peskine <gilles.peskine@arm.com>
Gesendet: Tuesday, 31 May 2022 23:37
An: Beat Heeb <heeb@oberon.ch>; psa-crypto@lists.trustedfirmware.org
Betreff: Re: [psa-crypto] Issues with PSA Cryptography API 1.1 PAKE Extension
Hi Beat,
Thank you very much for the feedback! We're only just starting work on our own implementation in Mbed TLS (https://github.com/orgs/Mbed-TLS/projects/1#column-17950140), so until now the
PAKE interface has only existed on paper for us.
I have some follow-up questions if you don't mind.
On 31/05/2022 17:02, Beat Heeb via psa-crypto wrote:
Reference: “PSA Cryptography API 1.1 PAKE Extension” 10/02/2022.
https://armmbed.github.io/mbed-crypto/1.1_PAKE_Extension.0-bet.0/psa_crypto_api_pake_ext.pdf
Issue 1
It is impossible to derive multiple keys from the common secret.
The suggested PAKE interface passes the resulting raw common secret directly to a key derivation operation. This is good to avoid direct usage of the secret but it makes it impossible to derive more than one key from the secret because the key derivation operation can only be used once. Deriving multiple keys is mandatory for some protocols for instance to get a session key for the rest of the pairing phase and in addition a long term key to establish further sessions.
It would be better to return the raw secret as a key which can only be used as input to a key derivation operation. This would be easy to use and allows for multiple derived keys.
The same problem exists for the key agreement interface which is also directly coupled to a key derivation operation. Again there exists protocols where multiple keys are needed, for instance one for outgoing and one for incoming messages. In the case of key agreement, the psa_raw_key_agreement() function can often be used as a workaround but returning a derivation only key instead of the coupling to a key derivation operation would be a more general and cleaner solution.
Could you clarify what you're missing here? Would you like to write the derived secret to persistent storage? It is possible to derive multiple keys in a single key derivation operation. Would you mind sharing what protocol(s) you can't implement with the existing
API?
The protocol we have in mind is HomeKit where several temporary keys as well as the long term secret key are derived from the SRP common secret. A single key derivation operation cannot be used because the separate keys are derived with
separate salt and info values.
Issue 2
The suggested interface cannot be implemented in an opaque driver.Opaque drivers are selected based on the key attributes provided. For a multi part operation the driver has to be selected by the first function called. For PAKE this is psa_pake_setup(). However, no key is passed to this function. The only key involved is passed to the psa_pake_set_password_key() function which is called later and cannot be used for driver selection because the driver cannot be changed during a multi part operation.
Indeed this kind of multi-stage operation is hard to adapt to drivers. For key derivation, which has a similar problem, we're bundling all the inputs before choosing a driver. But as you note PAKE have the additional twist that they might require communication
and accelerated operations before the secret key is known.
If the values are bundled in the driver interface but not in the outer interface, buffering of all provided values is needed in the core. Buffering the values in the core needs a potentially unbounded amount of memory which makes it difficult
or impossible to make a memory efficient implementation. Using the same bundling on the outer interface would solve this.
At the moment we've only defined an application interface, not a driver interface. I think we should allow ourselves to change the application interface as long as the driver interface isn't finalized, if it helps. But I don't know if the API is really the
problem: the difficulty seems to be inherent in the protocols.
If the “public key before salt” variant of SRP is the only critical protocol, it is maybe acceptable to ignore it. I guess this variant is not widely used.
Unfortunately, the problem is not easy to solve. A change in the interface of the psa_pake_setup() function would work fine in most cases:
psa_status_t psa_pake_setup(
psa_pake_operation_t *operation,
const psa_pake_cipher_suite_t *cipher_suite,
psa_key_id_t password,
const uint8_t *user_id, size_t user_id_len,
const uint8_t *peer_id, size_t peer_id_len,
psa_pake_role_t role);
(role, user_id, and peer_id are included because they are often needed to interpret the password value).
However, for some protocols the password hash cannot be calculated before some data is exchanged. In a variant of SRP-6 for instance the client first sends its public key to the server, the server then responds with the password salt and its own public key. The client therefore needs to calculate the public key before it receives the salt needed to calculate the password hash.
Issue 3
Missing support for ‘out of band’ setup calculations.
The suggested PAKE interface deliberately does not contain functions for setup calculation not directly involved in the PAKE protocol. This might be a good idea to keep things simple and easy to use. However, there must be a way to do calculations like the password hash somehow. Otherwise the whole PAKE interface turns out to be useless in many situations. In most PAKE protocols a password hash or password verifier is not just a hash but needs field or group calculations related to the main PAKE operation. To allow an implementation of all parts of a PAKE key exchange without relying on a second crypto library, it is mandatory to provide these functions somehow in PSA, in special PAKE functions or in another interface.
What's missing here? The input to the PAKE can be a key object. This can be, for example, the output of a password-based key derivation operation.
This is highly protocol dependent.
For SPAKE2+ for instance, the password hash consists of the values w0 and w1 on client side and w0 and L on server side. w0 and w1 are derived using PBKDF2 but in addition they must be reduced modulo the DH group order. L is the group scalar product of w1 and
the group base element. The reduction and the scalar multiplication are missing in the PSA API.
Lacking these operations, we could use the raw password as input instead of the derived values but this would compromise security, at least on the server side where no raw passwords should be kept.
A common approach is to expect the unreduced PBKDF2 values on client side but provide separate function for w0 and L to get the password hash on server side. This interface is used for instance in the Matter crypto PAL.
Issue 4
PAKE SIZE macros need more arguments.
The PAKE input and output size macro are defined with the argument list (alg, primitive, output_step). However, some input/output values depend on the digest size of the selected hash algorithm. This holds for instance for a SPAKE2+ confirmation key or the SRP client/server proofs.
It is therefore mandatory to include either the hash algorithm or the hash size in the argument list of the two macros.
I wonder if the hash should move from the cipher suite to the primitive? I'm not sure what knock-on effect this might have.
We will run a bit low on bits in the primitive value when we do that but I think it should work fine.
Regards
Beat
Thanks,
--
Gilles Peskine
PSA Crypto architect