-
Notifications
You must be signed in to change notification settings - Fork 28
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/* This file contains reference definitions for implementations of | ||
* SRP-6 in addition to the PSA Certified Crypto API v1.2 PAKE Extension | ||
* | ||
* 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) | ||
#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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Note to self: this may be worth a rationale comment when defined in the specification. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
* | ||
* 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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+) |
||
* 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there specific DH groups that could/should be used here?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RFC 5054 might be a better choice. |
||
* Diffie-Hellman group to be used. | ||
*/ | ||
#define PSA_KEY_TYPE_SRP_KEY_PAIR(group) \ | ||
((psa_key_type_t) (PSA_KEY_TYPE_SRP_KEY_PAIR_BASE | (group))) | ||
|
||
/** SRP public key. The server key (password verifier). | ||
* | ||
* The size of an SRP public key is the same as the corresponding private | ||
* key. See #PSA_KEY_TYPE_SRP_KEY_PAIR() and the documentation of each | ||
* Diffie-Hellman group for details. | ||
* To construct a SRP public key, it must be imported. The key size | ||
* in attributes must not be zero. | ||
* | ||
* \param group A value of type ::psa_dh_family_t that identifies the | ||
* Diffie-Hellman group to be used. | ||
*/ | ||
#define PSA_KEY_TYPE_SRP_PUBLIC_KEY(group) \ | ||
((psa_key_type_t) (PSA_KEY_TYPE_SRP_PUBLIC_KEY_BASE | (group))) | ||
|
||
/** Whether a key type is a SRP key (pair or public-only). */ | ||
#define PSA_KEY_TYPE_IS_SRP(type) \ | ||
((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ | ||
~PSA_KEY_TYPE_SRP_GROUP_MASK) == \ | ||
PSA_KEY_TYPE_SRP_PUBLIC_KEY_BASE) | ||
/** Whether a key type is a SRP key pair. */ | ||
#define PSA_KEY_TYPE_IS_SRP_KEY_PAIR(type) \ | ||
(((type) & ~PSA_KEY_TYPE_SRP_GROUP_MASK) == \ | ||
PSA_KEY_TYPE_SRP_KEY_PAIR_BASE) | ||
/** Whether a key type is a SRP public key. */ | ||
#define PSA_KEY_TYPE_IS_SRP_PUBLIC_KEY(type) \ | ||
(((type) & ~PSA_KEY_TYPE_SRP_GROUP_MASK) == \ | ||
PSA_KEY_TYPE_SRP_PUBLIC_KEY_BASE) | ||
/** Extract the curve from a SRP key type. */ | ||
#define PSA_KEY_TYPE_SRP_GET_FAMILY(type) \ | ||
((psa_ecc_family_t) (PSA_KEY_TYPE_IS_SRP(type) ? \ | ||
((type) & PSA_KEY_TYPE_SRP_GROUP_MASK) : \ | ||
0)) | ||
|
||
/** The Secure Remote Passwort key exchange (SRP) algorithm. | ||
* | ||
* This is SRP-6 as defined by RFC 2945 and RFC 5054, instantiated with the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is SRP-6a as defined by RFC 5054 including errata |
||
* following parameters: | ||
* | ||
* - The group is defined over a finite field using a secure prime. | ||
* - A cryptographic hash function. | ||
* | ||
* To select these parameters and set up the cipher suite, call these functions: | ||
* | ||
* \code | ||
* 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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
* \endcode | ||
* | ||
* After initializing a SRP operation, call: | ||
* | ||
* \code | ||
* psa_pake_setup(operation, password, cipher_suite); | ||
* psa_pake_set_role(operation, ...); | ||
* psa_pake_set_user(operation, ...); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is no server identity in this PAKE, setting a value should probably return an error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would suggest that both roles call |
||
* \endcode | ||
* | ||
* The password provided to the client side must be of type | ||
* #PSA_KEY_TYPE_SRP_KEY_PAIR. | ||
* The password provided to the server side must be of type | ||
* #PSA_KEY_TYPE_SRP_PUBLIC_KEY. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In SPAKE2+ we permitted the use of the key-pair here as well. Should we permit the same here, or was that a mistake? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. |
||
* | ||
* The role set by \c psa_pake_set_role() must be either | ||
* \c PSA_PAKE_ROLE_CLIENT or \c PSA_PAKE_ROLE_SERVER. | ||
* | ||
* For the SRP client key exchange call the following functions in any order: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We were rather more strict about the ordering in the SPAKE2+ definition. Is the flexibility here important? - e.g. to support different protocol flows regarding transmission of User Id and receipt of salt from the server? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, flexibility is important for that reason. |
||
* \code | ||
* // get salt | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_SALT, ...); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Client only requires the salt for password hashing (done outside the PAKE operation, to prepare the SRP-6 key-pair), and for some definitions of the key confirmation values. i.e. this might be unnecessary depending on the definition of the key confirmation values (see other comments). |
||
* // get server key | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); | ||
* // write client key | ||
* psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); | ||
* \endcode | ||
* | ||
* For the SRP server key exchange call the following functions in any order: | ||
* \code | ||
* // get salt | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_SALT, ...); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Server only requires the salt for some definitions of the key confirmation values. i.e. this might be unnecessary depending on the definition of the key confirmation values (see other comments). |
||
* // get client key | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); | ||
* // write server key | ||
* psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); | ||
* \endcode | ||
* | ||
* For the client proof phase call the following functions in this order: | ||
* \code | ||
* // send M1 | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_CONFIRM, ...); | ||
* // receive M2 | ||
* psa_pake_output(operation, #PSA_PAKE_STEP_CONFIRM, ...); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
(see also the comment for the server proof phase call) |
||
* // Get secret | ||
* psa_pake_get_shared_key() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The formulation of the shared key needs to be clarified.
Any of these might be appropriate... |
||
* \endcode | ||
* | ||
* For the server proof phase call the following functions in this order: | ||
* \code | ||
* // receive M1 | ||
* psa_pake_output(operation, #PSA_PAKE_STEP_CONFIRM, ...); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
(see also the comment for the client proof phase call) |
||
* // send M2 | ||
* psa_pake_input(operation, #PSA_PAKE_STEP_CONFIRM, ...); | ||
* // Get secret | ||
* psa_pake_get_shared_key() | ||
* \endcode | ||
* | ||
* The shared secret that is produced by SRP is pseudorandom. Although | ||
* it can be used directly as an encryption key, it is recommended to use | ||
* the shared secret as an input to a key derivation operation to produce | ||
* additional cryptographic keys. | ||
*/ | ||
#define PSA_ALG_SRP_6_BASE ((psa_algorithm_t) 0x0a000300) | ||
#define PSA_ALG_SRP_6(hash_alg) (PSA_ALG_SRP_6_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) | ||
#define PSA_ALG_IS_SRP_6(alg) (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_SRP_6_BASE) | ||
|
||
/** The salt. | ||
* | ||
* The format for both input and output at this step is plain binary data. | ||
*/ | ||
#define PSA_PAKE_STEP_SALT ((psa_pake_step_t)0x05) | ||
|
||
/** Diffie-Hellman groups defined in RFC 3526. | ||
* | ||
* This family includes groups with the following key sizes (in bits): | ||
* 1536, 2048, 3072, 4096, 6144, 8192. A given implementation may support | ||
* all of these sizes or only a subset. | ||
*/ | ||
#define PSA_DH_FAMILY_RFC3526 ((psa_dh_family_t) 0x05) | ||
|
||
#define PSA_ALG_SRP_PASSWORD_HASH_BASE ((psa_algorithm_t) 0x08800300) | ||
/** The SRP password to password-hash KDF. | ||
* It takes the password p, the salt s, and the user id u. | ||
* It calculates the password hash h as | ||
* h = H(salt || H(u || ":" || p) | ||
* where H is the given hash algorithm. | ||
* | ||
* This key derivation algorithm uses the following inputs, which must be | ||
* provided in the following order: | ||
* - #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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I presume this means that the intended use is to call |
||
*/ | ||
#define PSA_ALG_SRP_PASSWORD_HASH(hash_alg) \ | ||
(PSA_ALG_SRP_PASSWORD_HASH_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) | ||
|
||
/** Whether the specified algorithm is a key derivation algorithm constructed | ||
* using #PSA_ALG_SRP_PASSWORD_HASH(\p hash_alg). | ||
* | ||
* \param alg An algorithm identifier (value of type #psa_algorithm_t). | ||
* | ||
* \return 1 if \p alg is a key derivation algorithm constructed using #PSA_ALG_SRP_PASSWORD_HASH(), | ||
* 0 otherwise. This macro may return either 0 or 1 if \c alg is not a supported | ||
* key derivation algorithm identifier. | ||
*/ | ||
#define PSA_ALG_IS_SRP_PASSWORD_HASH(alg) \ | ||
(((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_SRP_PASSWORD_HASH_BASE) | ||
|
There was a problem hiding this comment.
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.