PSA PAKE: make cipher suite opaque

Hiding the structure of the cipher suite implementation allows for
greater flexibility.

To preserve maximum flexibility, the constructor is replaced by
individual setter/getter functions.

Convenience macros and or functions can be added later.

Signed-off-by: Janos Follath <janos.follath@arm.com>
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 074cc93..9220b2e 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -4140,38 +4140,188 @@
  */
 typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t;
 
-/** Construct a cipher suite for a password-authenticated key exchange.
+/** Retrieve the PAKE algorithm from a PAKE cipher suite.
  *
- * \param primitive          The primitive used in the cipher suite.
- * \param hash               The hash involved in the cipher suite.
- *                           (`PSA_ALG_XXX` values of type ::psa_algorithm_t
- *                           such that #PSA_ALG_IS_HASH(\c alg) is true.)
- * \param algorithm1         Additional algorithm if needed in the cipher suite,
- *                           0 otherwise.
- * \param bits1              A bit size qualifier if needed for \p algorithm1,
- *                           0 otherwise.
- * \param algorithm2         Additional algorithm if needed in the cipher suite,
- *                           0 otherwise.
- * \param bits2              A bit size qualifier if needed for \p algorithm2,
- *                           0 otherwise.
- * \param options            Additional options to be included with the cipher
- *                           suite if needed, 0 otherwise.
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] cipher_suite     The cipher suite structure to query.
+ *
+ * \return The PAKE algorithm stored in the cipher suite structure.
+ */
+static psa_algorithm_t psa_pake_cs_get_algorithm(
+                           const psa_pake_cipher_suite_t* cipher_suite
+                           );
+
+/** Declare the PAKE algorithm for the cipher suite.
+ *
+ * This function overwrites any PAKE algorithm
+ * previously set in \p cipher_suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] cipher_suite    The cipher suite structure to write to.
+ * \param algorithm            The PAKE algorithm to write.
+ *                             (`PSA_ALG_XXX` values of type ::psa_algorithm_t
+ *                             such that #PSA_ALG_IS_PAKE(\c alg) is true.)
+ *                             If this is 0, the PAKE algorithm in
+ *                             \p cipher_suite becomes unspecified.
+ */
+static void psa_pake_cs_set_algorithm(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           psa_algorithm_t algorithm
+                           );
+
+/** Retrieve the primitive type from a PAKE cipher suite.
+ *
+ * This function may be declared as `static` (i.e. without external linkage).
+ * This function may be provided as a function-like macro, but in this case it
+ * must evaluate its argument exactly once.
  *
  * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`
  * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true)
  * for more information.
  *
- * \retval The constructed cipher suite.
+ * \param[in] cipher_suite     The cipher suite structure to query.
+ *
+ * \return The primitive type stored in the cipher suite structure.
  */
-static psa_pake_cipher_suite_t psa_pake_cipher_suite(
-                                    psa_pake_primitive_t primitive,
-                                    psa_algorithm_t hash,
-                                    psa_algorithm_t algorithm1,
-                                    psa_pake_bits_t bits1,
-                                    psa_algorithm_t algorithm2,
-                                    psa_pake_bits_t bits2,
-                                    psa_pake_cipher_suite_options_t options
-                                    );
+static psa_pake_primitive_type_t psa_pake_cs_get_type(
+                           const psa_pake_cipher_suite_t* cipher_suite
+                           );
+
+/** Declare the primitive type for a PAKE cipher suite.
+ *
+ * This function overwrites any primitive type
+ * previously set in \p cipher_suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] cipher_suite    The cipher suite structure to write to.
+ * \param type                 The primitive type to write.
+ *                             If this is 0, the primitive type in
+ *                             \p cipher_suite becomes unspecified.
+ */
+static void psa_pake_cs_set_type(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           psa_pake_primitive_type_t type
+                           );
+
+/** Retrieve the primitive family from a PAKE cipher suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] cipher_suite      The cipher suite structure to query.
+ *
+ * \return The primitive family stored in the cipher suite structure.
+ */
+static uint8_t psa_pake_cs_get_family(
+                           const psa_pake_cipher_suite_t* cipher_suite
+                           );
+
+/** Declare the primitive family for a PAKE cipher suite.
+ *
+ * This function overwrites any primitive family
+ * previously set in \p cipher_suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] cipher_suite     The cipher suite structure to write to.
+ * \param family                The primitive family to write.
+ *                              If this is 0, the primitive family in
+ *                              \p cipher_suite becomes unspecified. The
+ *                              interpretation of this parameter depends on
+ *                              the primitive type, for more information consult the
+ *                              documentation of individual
+ *                              ::psa_pake_primitive_type_t constants).
+ */
+static void psa_pake_cs_set_family(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           uint8_t family
+                           );
+
+/** Retrieve the primitive bits from a PAKE cipher suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] cipher_suite      The cipher suite structure to query.
+ *
+ * \return The primitive bits stored in the cipher suite structure.
+ */
+static size_t psa_pake_cs_get_bits(const psa_pake_cipher_suite_t* cipher_suite);
+
+/** Declare the primitive bits for a PAKE cipher suite.
+ *
+ * This function overwrites any primitive bits
+ * previously set in \p cipher_suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] cipher_suite     The cipher suite structure to write to.
+ * \param bits                  The primitive bits to write.
+ *                              If this is 0, the primitive bits in
+ *                              \p cipher_suite becomes unspecified. The
+ *                              interpretation of this parameter depends on
+ *                              the family, for more information consult the
+ *                              documentation of individual
+ *                              ::psa_pake_primitive_type_t constants).
+ */
+static void psa_pake_cs_set_bits(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           size_t bits
+                           );
+
+/** Retrieve the hash algorithm from a PAKE cipher suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] cipher_suite      The cipher suite structure to query.
+ *
+ * \return The hash algorithm stored in the cipher suite structure.
+ */
+static psa_algorithm_t psa_pake_cs_get_hash(
+                           const psa_pake_cipher_suite_t* cipher_suite
+                           );
+
+/** Declare the hash algorithm for a PAKE cipher suite.
+ *
+ * This function overwrites any hash algorithm
+ * previously set in \p cipher_suite.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX`
+ * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true)
+ * for more information.
+ *
+ * \param[out] cipher_suite     The cipher suite structure to write to.
+ * \param hash                  The hash involved in the cipher suite.
+ *                              (`PSA_ALG_XXX` values of type ::psa_algorithm_t
+ *                              such that #PSA_ALG_IS_HASH(\c alg) is true.)
+ *                              If this is 0, the hash algorithm in
+ *                              \p cipher_suite becomes unspecified.
+ */
+static void psa_pake_cs_set_hash(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           psa_algorithm_t hash
+                           );
 
 /** The type of the state data structure for PAKE operations.
  *
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index f289caf..881abcb 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -463,36 +463,82 @@
 
 struct psa_pake_cipher_suite_s
 {
-    psa_pake_primitive_t primitive;
+    psa_algorithm_t algorithm;
+    psa_pake_primitive_type_t type;
+    uint8_t family;
+    size_t  bits;
     psa_algorithm_t hash;
-    psa_algorithm_t algorithm1;
-    psa_pake_bits_t bits1;
-    psa_algorithm_t algorithm2;
-    psa_pake_bits_t bits2;
-    psa_pake_cipher_suite_options_t options;
 };
 
-static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite(
-                                    psa_pake_primitive_t primitive,
-                                    psa_algorithm_t hash,
-                                    psa_algorithm_t algorithm1,
-                                    psa_pake_bits_t bits1,
-                                    psa_algorithm_t algorithm2,
-                                    psa_pake_bits_t bits2,
-                                    psa_pake_cipher_suite_options_t options
-                                    )
+static inline void psa_pake_cs_set_algorithm(
+    psa_pake_cipher_suite_t *cipher_suite,
+    psa_algorithm_t algorithm)
 {
-    struct psa_pake_cipher_suite_s cipher_suite;
+    if( !PSA_ALG_IS_PAKE(algorithm) )
+        cipher_suite->algorithm = 0;
+    else
+        cipher_suite->algorithm = algorithm;
+}
 
-    cipher_suite.primitive = primitive;
-    cipher_suite.hash = hash;
-    cipher_suite.algorithm1 = algorithm1;
-    cipher_suite.bits1 = bits1;
-    cipher_suite.algorithm2 = algorithm2;
-    cipher_suite.bits2 = bits2;
-    cipher_suite.options = options;
+static inline psa_algorithm_t psa_pake_cs_get_algorithm(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return( cipher_suite->algorithm );
+}
 
-    return cipher_suite;
+static inline psa_pake_primitive_type_t psa_pake_cs_get_type(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return( cipher_suite->type );
+}
+
+static inline void psa_pake_cs_set_type(
+    psa_pake_cipher_suite_t *cipher_suite,
+    psa_pake_primitive_type_t type)
+{
+    cipher_suite->type = type;
+}
+
+static inline uint8_t psa_pake_cs_get_family(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return( cipher_suite->family );
+}
+
+static inline void psa_pake_cs_set_family(
+    psa_pake_cipher_suite_t *cipher_suite,
+    uint8_t family)
+{
+    cipher_suite->family = family;
+}
+
+static inline size_t psa_pake_cs_get_bits(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return( cipher_suite->bits );
+}
+
+static inline void psa_pake_cs_set_bits(
+    psa_pake_cipher_suite_t *cipher_suite,
+    size_t bits)
+{
+    cipher_suite->bits = bits;
+}
+
+static inline psa_algorithm_t psa_pake_cs_get_hash(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return( cipher_suite->hash );
+}
+
+static inline void psa_pake_cs_set_hash(
+    psa_pake_cipher_suite_t *cipher_suite,
+    psa_algorithm_t hash)
+{
+    if( !PSA_ALG_IS_HASH(hash) )
+        cipher_suite->hash = 0;
+    else
+        cipher_suite->hash = hash;
 }
 
 struct psa_pake_operation_s
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 9a9f69e..bed48f7 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1969,21 +1969,22 @@
 /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm.
  *
  * J-PAKE can be instantiated over finite fields or elliptic curves. This can
- * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_DH or
- * #PSA_PAKE_PRIMITIVE_TYPE_ECC to #PSA_PAKE_PRIMITIVE respectively, when
- * creating the cipher suite.
+ * be achieved by setting either #PSA_PAKE_PRIMITIVE_TYPE_DH or
+ * #PSA_PAKE_PRIMITIVE_TYPE_ECC respectively in the cipher suite (see
+ * ::psa_pake_cipher_suite_t) via psa_pake_cs_set_type(). (Before using the
+ * cipher suite the field or curve must be fully specified by calling
+ * psa_pake_cs_set_family() and psa_pake_cs_set_bits() as well. For more
+ * information refer to the documentation of the individual
+ * `PSA_PAKE_PRIMITIVE_TYPE_XXX` constants.)
+ *
+ * J-PAKE can be used with any secure cryptographic hash function. The choice
+ * of hash must be supplied to the cipher suite by calling
+ * psa_pake_cs_set_hash().
  *
  * In theory the algorithm works with any non-interactive zero-knowledge proof.
  * Implementations of the present specification use Schnorr NIZKP and this does
  * not need to be configured in the cipher suites.
  *
- * J-PAKE can be used with any secure cryptographic hash function, the choice
- * of hash must be supplied to the psa_pake_cipher_suite() as the second
- * parameter (\p hash).
- *
- * All the remaining parameters passed to psa_pake_cipher_suite() when creating
- * the cipher suite must be 0.
- *
  * The key exchange flow for JPAKE is as follows:
  * -# To get the first round data that needs to be sent to the peer, call
  *      // Get g1