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

Add definitions required by SRP-6. #178

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

oberon-sk
Copy link

The PSA Certified Crypto API v1.2 PAKE Extension requires some additional definitions to support SRP-6 as defined by RFC 2945 and RFC 5054 to be embedded in, or included by, psa/crypto.h.

This PR provides a proposal.

Signed-off-by: Oberon microsystems

Signed-off-by: Stephan Koch <koch@oberon.ch>
@athoelke athoelke marked this pull request as draft March 4, 2024 14:49
@athoelke athoelke added enhancement New feature or request Crypto API Issue or PR related to the Cryptography API proposal An RFC, or proposal for discussion labels Mar 4, 2024
@athoelke athoelke added this to the Crypto API 1.x milestone Mar 4, 2024
Copy link
Contributor

@athoelke athoelke left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution!

Some further clarification of the definition of the protocol, as the public documentation has various definitions for some of the computational steps. This is necessary to ensure compatible implementations of algorithms in the Crypto API.

If we need additional flexibility for different uses of SRP-6, then we will need additional algorithm identifiers, or other parameterisation of the PAKE cipher-suite.

#define PSA_KEY_TYPE_SRP_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4700)
#define PSA_KEY_TYPE_SRP_GROUP_MASK ((psa_key_type_t) 0x00ff)

/** SRP key pair. Both the client and server key.
Copy link
Contributor

Choose a reason for hiding this comment

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

The definition of these SRP-6 keys is technically equivalent to FFDH keys, in terms of key content and calculation of the public key from the private key.

However, there may be a good reason for maintaining a separate key type definition for SRP-6 keys instead of reusing the existing PSA_KEY_TYPE_DH_KEY_PAIR(): The derivation of an SRP-6 key is different to the default method for FFDH keys in the Crypto API.

  • An FFDH key-pair is derived by repeated sampling of the KDF output to find a value in the required range [1, N-1].
  • A SRP-6 key-pair is constructed by zero-padding the fixed-size output of the password-hash. The original SRP hash outputs only 160 bits (for SHA1).

Note to self: this may be worth a rationale comment when defined in the specification.

Copy link
Contributor

Choose a reason for hiding this comment

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

Some descriptions of SRP-6 show the client private key being the output of a simple hash - so we need to ensure the correct construction of an SRP-6 key from an imported data buffer (the hash output), as well as construction via a KDF (such as the original SRP specification double-hash algorithm).

For a general KDF, how does psa_key_derivation_output_key() know how much data to extract when deriving the SRP-6 key? The KDF presented in the SRP definition only outputs the hash output size. What about KDFs that do not have limited output? - we can either define the behavior explicitly, or recommend the application extract the required number of KDF bytes, and then import the SRP key?

Copy link
Author

Choose a reason for hiding this comment

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

This is a general problem for the derivation of structured keys. The PSA core has to ‘know’ somehow how much data the driver needs to construct the key. The “psa-driver-interface.md” document mentions this under “Open questions around cooked key derivation”. The idea of an additional entry point to determine the expected length mentioned there is possibly the best solution.
For trial-and-error type key derivation like FFDH the driver simply returns PSA_ERROR_INSUFFICIENT_DATA to signal the core to call it again with the next chunk of data.

* The corresponding public key (password verifier) can be exported using
* psa_export_public_key(). See also #PSA_KEY_TYPE_SRP_PUBLIC_KEY().
*
* \param group A value of type ::psa_dh_family_t that identifies the
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there specific DH groups that could/should be used here?

  • Crypto API currently just defines the RFC 7919 family
  • This header defines another RFC 3526 family
  • The SRP-for-TLS reference (RFC 5054) defines another set of FFDH groups

Copy link
Author

Choose a reason for hiding this comment

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

RFC 5054 might be a better choice.

* These definitions must be embedded in, or included by, psa/crypto.h
*/

#define PSA_KEY_TYPE_SRP_KEY_PAIR_BASE ((psa_key_type_t) 0x7700)
Copy link
Contributor

Choose a reason for hiding this comment

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

This value works well with the current set of DH key values: it has the same parity as the PSA_KEY_TYPE_DH_KEY_PAIR() base value, so existing DH family values can be used.


/** The Secure Remote Passwort key exchange (SRP) algorithm.
*
* This is SRP-6 as defined by RFC 2945 and RFC 5054, instantiated with the
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this SRP-6 or SRP-6a? the latter calculates the multiplier value k using Hash(N || PAD(g)), instead of using the fixed value 3. This distinction is not always correctly defined in references to this algorithm.

Copy link
Author

Choose a reason for hiding this comment

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

This is SRP-6a as defined by RFC 5054 including errata (k = Hash(N || PAD(g)).

* psa_pake_cipher_suite_t cipher_suite = PSA_PAKE_CIPHER_SUITE_INIT;
* psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_SRP_6(hash));
* psa_pake_cs_set_primitive(&cipher_suite,
* PSA_PAKE_PRIMITIVE(type, family, bits));
Copy link
Contributor

Choose a reason for hiding this comment

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

The parameters here could be more fully specified - something to fix in the specification itself.

* // send M1
* psa_pake_input(operation, #PSA_PAKE_STEP_CONFIRM, ...);
* // receive M2
* psa_pake_output(operation, #PSA_PAKE_STEP_CONFIRM, ...);
Copy link
Contributor

Choose a reason for hiding this comment

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

The definition of M2 needs to be clarified. I can find more than 3 different formulations across different SRP-6 documentation.

The definition of M1 and M2 may result in not requiring some of the inputs to the operation (client identity and salt).

Copy link
Author

Choose a reason for hiding this comment

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

The variant where M1 = H(H(N) XOR H(g) | H(U) | s | A | B | K) and M2 = H(A | M1 | K) seems to be the clear standard.
It is defined or used by:

  • RFC2945
  • RFC5054 (by referring to RFC2945)
  • srp.stanford.edu/design (for SRP-3, SRP-6, and SRP-6a)
  • The Stanford reference implementation
  • The reference implementation on Wikipedia
  • The SRP test vectors on github.com/secure-remote-password/test-vectors
  • HomeKit (by referring to the Stanford reference implementation)
  • The Wolfcrypt library

(see also the comment for the server proof phase call)

* For the server proof phase call the following functions in this order:
* \code
* // receive M1
* psa_pake_output(operation, #PSA_PAKE_STEP_CONFIRM, ...);
Copy link
Contributor

Choose a reason for hiding this comment

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

The definition of M1 needs to be clarified. I can find different formulations across different SRP-6 documentation.

The definition of M1 and M2 may result in not requiring some of the inputs to the operation (client identity and salt).

Copy link
Author

Choose a reason for hiding this comment

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

The variant where M1 = H(H(N) XOR H(g) | H(U) | s | A | B | K) and M2 = H(A | M1 | K) seems to be the clear standard.
It is defined or used by:

  • RFC2945
  • RFC5054 (by referring to RFC2945)
  • srp.stanford.edu/design (for SRP-3, SRP-6, and SRP-6a)
  • The Stanford reference implementation
  • The reference implementation on Wikipedia
  • The SRP test vectors on github.com/secure-remote-password/test-vectors
  • HomeKit (by referring to the Stanford reference implementation)
  • The Wolfcrypt library

(see also the comment for the client proof phase call)

* // receive M2
* psa_pake_output(operation, #PSA_PAKE_STEP_CONFIRM, ...);
* // Get secret
* psa_pake_get_shared_key()
Copy link
Contributor

Choose a reason for hiding this comment

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

The formulation of the shared key needs to be clarified.

  • In RFC 2945, it uses an interleaved SHA1 to construct an unbiased pseudo-random 320-bit value from the pre-master secret (biased output of a function on the DH group).
  • In RFC 5054, the description stops at the pre-mater secret (S), a biased output of a function on the DH group.
  • Elsewhere it just uses Hash(S), for some value of 'Hash'.

Any of these might be appropriate...

* - #PSA_KEY_DERIVATION_INPUT_INFO is the user id.
* - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password.
* - #PSA_KEY_DERIVATION_INPUT_SALT is the salt.
* The output has to be read as a key of type PSA_KEY_TYPE_SRP_KEY_PAIR.
Copy link
Contributor

Choose a reason for hiding this comment

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

I presume this means that the intended use is to call psa_key_derivation_output_key() requesting a key of that type, with a key size that matches the bit-size of the DH group used for the primitive in the PAKE cipher-suite?

*
* The size of a SRP key is the size associated with the Diffie-Hellman
* group. See the documentation of each Diffie-Hellman group for details.
* To construct a SRP key pair, the password hash must be imported.
Copy link
Contributor

Choose a reason for hiding this comment

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

Later, the documentation talks about constructing an SRP-6 key as output from a password-hash type of KDF, rather than by using psa_import_key() on some data.

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, it should be:

"To construct an SRP key pair, it must either be output from a key derivation operation, or imported."

(similar to SPAKE2+)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Crypto API Issue or PR related to the Cryptography API enhancement New feature or request proposal An RFC, or proposal for discussion
Projects
Development

Successfully merging this pull request may close these issues.

2 participants