Merge remote-tracking branch 'upstream/development' into psa-m-aead-merge

Also fiixed the following merge problems:

crypto_struct.h   : Added MBEDTLS_PRIVATE to psa_aead_operation_s
                    members (merge conflict)
psa_crypto_aead.c : Added ciphertext_length to mbedtls_gcm_finish
                    call (change of API during development)

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 6aa7ccc..b3ef363 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -112,12 +112,6 @@
  * This macro returns a suitable initializer for a key attribute structure
  * of type #psa_key_attributes_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_KEY_ATTRIBUTES_INIT {0}
-#endif
 
 /** Return an initial value for a key attributes structure.
  */
@@ -938,8 +932,8 @@
  *   \endcode
  *
  * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation. */
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
 typedef struct psa_hash_operation_s psa_hash_operation_t;
 
 /** \def PSA_HASH_OPERATION_INIT
@@ -947,12 +941,6 @@
  * This macro returns a suitable initializer for a hash operation object
  * of type #psa_hash_operation_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_HASH_OPERATION_INIT {0}
-#endif
 
 /** Return an initial value for a hash operation object.
  */
@@ -1307,9 +1295,10 @@
  *   operation = psa_mac_operation_init();
  *   \endcode
  *
+ *
  * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation. */
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
 typedef struct psa_mac_operation_s psa_mac_operation_t;
 
 /** \def PSA_MAC_OPERATION_INIT
@@ -1317,12 +1306,6 @@
  * This macro returns a suitable initializer for a MAC operation object of type
  * #psa_mac_operation_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_MAC_OPERATION_INIT {0}
-#endif
 
 /** Return an initial value for a MAC operation object.
  */
@@ -1732,8 +1715,8 @@
  *   \endcode
  *
  * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation. */
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
 typedef struct psa_cipher_operation_s psa_cipher_operation_t;
 
 /** \def PSA_CIPHER_OPERATION_INIT
@@ -1741,12 +1724,6 @@
  * This macro returns a suitable initializer for a cipher operation object of
  * type #psa_cipher_operation_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_CIPHER_OPERATION_INIT {0}
-#endif
 
 /** Return an initial value for a cipher operation object.
  */
@@ -2261,8 +2238,8 @@
  *   \endcode
  *
  * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation. */
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
 typedef struct psa_aead_operation_s psa_aead_operation_t;
 
 /** \def PSA_AEAD_OPERATION_INIT
@@ -2270,12 +2247,6 @@
  * This macro returns a suitable initializer for an AEAD operation object of
  * type #psa_aead_operation_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_AEAD_OPERATION_INIT {0}
-#endif
 
 /** Return an initial value for an AEAD operation object.
  */
@@ -3260,8 +3231,8 @@
  *   \endcode
  *
  * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation.
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice.
  */
 typedef struct psa_key_derivation_s psa_key_derivation_operation_t;
 
@@ -3270,12 +3241,6 @@
  * This macro returns a suitable initializer for a key derivation operation
  * object of type #psa_key_derivation_operation_t.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_KEY_DERIVATION_OPERATION_INIT {0}
-#endif
 
 /** Return an initial value for a key derivation operation object.
  */
@@ -3717,7 +3682,6 @@
  *   The following key types defined in this specification follow this scheme:
  *
  *     - #PSA_KEY_TYPE_AES;
- *     - #PSA_KEY_TYPE_ARC4;
  *     - #PSA_KEY_TYPE_CAMELLIA;
  *     - #PSA_KEY_TYPE_DERIVE;
  *     - #PSA_KEY_TYPE_HMAC;
@@ -3841,7 +3805,7 @@
  * This function calculates output bytes from a key derivation algorithm and
  * compares those bytes to an expected value in constant time.
  * If you view the key derivation's output as a stream of bytes, this
- * function destructively reads the requested number of bytes from the
+ * function destructively reads the expected number of bytes from the
  * stream before comparing them.
  * The operation's capacity decreases by the number of bytes read.
  *
@@ -3860,13 +3824,13 @@
  * psa_key_derivation_abort().
  *
  * \param[in,out] operation The key derivation operation object to read from.
- * \param[in] expected_output Buffer where the output will be written.
+ * \param[in] expected_output Buffer containing the expected derivation output.
  * \param output_length     Length ot the expected output; this is also the
  *                          number of bytes that will be read.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_SIGNATURE
- *         The output was read successfully, but if differs from the expected
+ *         The output was read successfully, but it differs from the expected
  *         output.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         One of the inputs was a key whose policy didn't allow
@@ -3876,7 +3840,7 @@
  *                          \p output_length bytes. Note that in this case,
  *                          the operation's capacity is set to 0, thus
  *                          subsequent calls to this function will not
- *                          succeed, even with a smaller output buffer.
+ *                          succeed, even with a smaller expected output.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps).
@@ -3941,7 +3905,7 @@
  *                          the length of the expected value. In this case,
  *                          the operation's capacity is set to 0, thus
  *                          subsequent calls to this function will not
- *                          succeed, even with a smaller output buffer.
+ *                          succeed, even with a smaller expected output.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps).
diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h
index 7d8bc1a..cdecb28 100644
--- a/include/psa/crypto_builtin_composites.h
+++ b/include/psa/crypto_builtin_composites.h
@@ -32,6 +32,7 @@
 
 #ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H
 #define PSA_CRYPTO_BUILTIN_COMPOSITES_H
+#include "mbedtls/private_access.h"
 
 #include <psa/crypto_driver_common.h>
 
@@ -47,11 +48,11 @@
 typedef struct
 {
     /** The HMAC algorithm in use */
-    psa_algorithm_t alg;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
     /** The hash context. */
     struct psa_hash_operation_s hash_ctx;
     /** The HMAC part of the context. */
-    uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
 } mbedtls_psa_hmac_operation_t;
 
 #define MBEDTLS_PSA_HMAC_OPERATION_INIT {0, PSA_HASH_OPERATION_INIT, {0}}
@@ -61,17 +62,17 @@
 
 typedef struct
 {
-    psa_algorithm_t alg;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
     union
     {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+        unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
-        mbedtls_psa_hmac_operation_t hmac;
+        mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac);
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
-        mbedtls_cipher_context_t cmac;
+        mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac);
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-    } ctx;
+    } MBEDTLS_PRIVATE(ctx);
 } mbedtls_psa_mac_operation_t;
 
 #define MBEDTLS_PSA_MAC_OPERATION_INIT {0, {0}}
diff --git a/include/psa/crypto_builtin_primitives.h b/include/psa/crypto_builtin_primitives.h
index 75801a1..31f4aa6 100644
--- a/include/psa/crypto_builtin_primitives.h
+++ b/include/psa/crypto_builtin_primitives.h
@@ -32,6 +32,7 @@
 
 #ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H
 #define PSA_CRYPTO_BUILTIN_PRIMITIVES_H
+#include "mbedtls/private_access.h"
 
 #include <psa/crypto_driver_common.h>
 
@@ -39,17 +40,13 @@
  * Hash multi-part operation definitions.
  */
 
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
 #include "mbedtls/md5.h"
 #include "mbedtls/ripemd160.h"
 #include "mbedtls/sha1.h"
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \
@@ -61,32 +58,26 @@
 
 typedef struct
 {
-    psa_algorithm_t alg;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
     union
     {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_MD2_C)
-        mbedtls_md2_context md2;
-#endif
-#if defined(MBEDTLS_MD4_C)
-        mbedtls_md4_context md4;
-#endif
+        unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */
 #if defined(MBEDTLS_MD5_C)
-        mbedtls_md5_context md5;
+        mbedtls_md5_context MBEDTLS_PRIVATE(md5);
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
-        mbedtls_ripemd160_context ripemd160;
+        mbedtls_ripemd160_context MBEDTLS_PRIVATE(ripemd160);
 #endif
 #if defined(MBEDTLS_SHA1_C)
-        mbedtls_sha1_context sha1;
+        mbedtls_sha1_context MBEDTLS_PRIVATE(sha1);
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        mbedtls_sha256_context sha256;
+        mbedtls_sha256_context MBEDTLS_PRIVATE(sha256);
 #endif
 #if defined(MBEDTLS_SHA512_C)
-        mbedtls_sha512_context sha512;
+        mbedtls_sha512_context MBEDTLS_PRIVATE(sha512);
 #endif
-    } ctx;
+    } MBEDTLS_PRIVATE(ctx);
 } mbedtls_psa_hash_operation_t;
 
 #define MBEDTLS_PSA_HASH_OPERATION_INIT {0, {0}}
@@ -110,10 +101,13 @@
 
 typedef struct {
     /* Context structure for the Mbed TLS cipher implementation. */
-    psa_algorithm_t alg;
-    uint8_t iv_length;
-    uint8_t block_length;
-    mbedtls_cipher_context_t cipher;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    uint8_t MBEDTLS_PRIVATE(iv_length);
+    uint8_t MBEDTLS_PRIVATE(block_length);
+    union {
+        unsigned int MBEDTLS_PRIVATE(dummy);
+        mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher);
+    } MBEDTLS_PRIVATE(ctx);
 } mbedtls_psa_cipher_operation_t;
 
 #define MBEDTLS_PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}}
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index eb16492..64d8c58 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -5,7 +5,7 @@
  */
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
 /**
- * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in config.h,
+ * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h,
  * this file determines which cryptographic mechanisms are enabled
  * through the PSA Cryptography API (\c psa_xxx() functions).
  *
@@ -24,7 +24,7 @@
  */
 #else
 /**
- * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in config.h,
+ * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h,
  * this file is not used, and cryptographic mechanisms are supported
  * through the PSA API if and only if they are supported through the
  * mbedtls_xxx API.
@@ -69,8 +69,6 @@
 #define PSA_WANT_ALG_GCM                        1
 #define PSA_WANT_ALG_HKDF                       1
 #define PSA_WANT_ALG_HMAC                       1
-#define PSA_WANT_ALG_MD2                        1
-#define PSA_WANT_ALG_MD4                        1
 #define PSA_WANT_ALG_MD5                        1
 #define PSA_WANT_ALG_OFB                        1
 /* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
@@ -95,12 +93,7 @@
 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384         1
 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512         1
 #define PSA_WANT_ECC_MONTGOMERY_255             1
-/*
- * Curve448 is not yet supported via the PSA API in Mbed TLS
- * (https://github.com/ARMmbed/mbedtls/issues/4249). Thus, do not enable it by
- * default.
- */
-//#define PSA_WANT_ECC_MONTGOMERY_448             1
+#define PSA_WANT_ECC_MONTGOMERY_448             1
 #define PSA_WANT_ECC_SECP_K1_192                1
 /*
  * SECP224K1 is buggy via the PSA API in Mbed TLS
@@ -118,7 +111,6 @@
 #define PSA_WANT_KEY_TYPE_DERIVE                1
 #define PSA_WANT_KEY_TYPE_HMAC                  1
 #define PSA_WANT_KEY_TYPE_AES                   1
-#define PSA_WANT_KEY_TYPE_ARC4                  1
 #define PSA_WANT_KEY_TYPE_CAMELLIA              1
 #define PSA_WANT_KEY_TYPE_CHACHA20              1
 #define PSA_WANT_KEY_TYPE_DES                   1
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index a7b4ab5..2c0b106 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -27,6 +27,7 @@
 
 #ifndef PSA_CRYPTO_EXTRA_H
 #define PSA_CRYPTO_EXTRA_H
+#include "mbedtls/private_access.h"
 
 #include "mbedtls/platform_util.h"
 
@@ -39,7 +40,7 @@
 /* UID for secure storage seed */
 #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52
 
-/* See config.h for definition */
+/* See mbedtls_config.h for definition */
 #if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT)
 #define MBEDTLS_PSA_KEY_SLOT_COUNT 32
 #endif
@@ -71,7 +72,7 @@
     psa_key_attributes_t *attributes,
     psa_algorithm_t alg2)
 {
-    attributes->core.policy.alg2 = alg2;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2;
 }
 
 /** Retrieve the enrollment algorithm policy from key attributes.
@@ -83,7 +84,7 @@
 static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->core.policy.alg2 );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) );
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -141,8 +142,8 @@
     psa_key_attributes_t *attributes,
     psa_key_slot_number_t slot_number )
 {
-    attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
-    attributes->slot_number = slot_number;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
+    attributes->MBEDTLS_PRIVATE(slot_number) = slot_number;
 }
 
 /** Remove the slot number attribute from a key attribute structure.
@@ -154,7 +155,7 @@
 static inline void psa_clear_key_slot_number(
     psa_key_attributes_t *attributes )
 {
-    attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
 }
 
 /** Register a key that is already present in a secure element.
@@ -226,26 +227,26 @@
 typedef struct mbedtls_psa_stats_s
 {
     /** Number of slots containing key material for a volatile key. */
-    size_t volatile_slots;
+    size_t MBEDTLS_PRIVATE(volatile_slots);
     /** Number of slots containing key material for a key which is in
      * internal persistent storage. */
-    size_t persistent_slots;
+    size_t MBEDTLS_PRIVATE(persistent_slots);
     /** Number of slots containing a reference to a key in a
      * secure element. */
-    size_t external_slots;
+    size_t MBEDTLS_PRIVATE(external_slots);
     /** Number of slots which are occupied, but do not contain
      * key material yet. */
-    size_t half_filled_slots;
+    size_t MBEDTLS_PRIVATE(half_filled_slots);
     /** Number of slots that contain cache data. */
-    size_t cache_slots;
+    size_t MBEDTLS_PRIVATE(cache_slots);
     /** Number of slots that are not used for anything. */
-    size_t empty_slots;
+    size_t MBEDTLS_PRIVATE(empty_slots);
     /** Number of slots that are locked. */
-    size_t locked_slots;
+    size_t MBEDTLS_PRIVATE(locked_slots);
     /** Largest key id value among open keys in internal persistent storage. */
-    psa_key_id_t max_open_internal_key_id;
+    psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id);
     /** Largest key id value among open keys in secure elements. */
-    psa_key_id_t max_open_external_key_id;
+    psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id);
 } mbedtls_psa_stats_t;
 
 /** \brief Get statistics about
@@ -813,6 +814,1009 @@
 
 /** @} */
 
+/** \addtogroup crypto_types
+ * @{
+ */
+
+#define PSA_ALG_CATEGORY_PAKE                   ((psa_algorithm_t)0x0a000000)
+
+/** Whether the specified algorithm is a password-authenticated key exchange.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a password-authenticated key exchange (PAKE)
+ *         algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \p alg is not a supported
+ *         algorithm identifier.
+ */
+#define PSA_ALG_IS_PAKE(alg)                                        \
+    (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE)
+
+/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm.
+ *
+ * This is J-PAKE as defined by RFC 8236, instantiated with the following
+ * parameters:
+ *
+ * - The group can be either an elliptic curve or defined over a finite field.
+ * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the
+ *   J-PAKE algorithm.
+ * - A cryptographic hash function.
+ *
+ * To select these parameters and set up the cipher suite, call these functions
+ * in any order:
+ *
+ * \code
+ * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE);
+ * psa_pake_cs_set_primitive(cipher_suite,
+ *                           PSA_PAKE_PRIMITIVE(type, family, bits));
+ * psa_pake_cs_set_hash(cipher_suite, hash);
+ * \endcode
+ *
+ * For more information on how to set a specific curve or field, refer to the
+ * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.
+ *
+ * After initializing a J-PAKE operation, call
+ *
+ * \code
+ * psa_pake_setup(operation, cipher_suite);
+ * psa_pake_set_user(operation, ...);
+ * psa_pake_set_peer(operation, ...);
+ * psa_pake_set_password_key(operation, ...);
+ * \endcode
+ *
+ * The password is read as a byte array and must be non-empty. This can be the
+ * password itself (in some pre-defined character encoding) or some value
+ * derived from the password as mandated by some higher level protocol.
+ *
+ * (The implementation converts this byte array to a number as described in
+ * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_
+ * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here
+ * \c q is order of the group defined by the primitive set in the cipher suite.
+ * The \c psa_pake_set_password_xxx() functions return an error if the result
+ * of the reduction is 0.)
+ *
+ * The key exchange flow for J-PAKE is as follows:
+ * -# To get the first round data that needs to be sent to the peer, call
+ *    \code
+ *    // Get g1
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Get the ZKP public key for x1
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Get the ZKP proof for x1
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    // Get g2
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Get the ZKP public key for x2
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Get the ZKP proof for x2
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    \endcode
+ * -# To provide the first round data received from the peer to the operation,
+ *    call
+ *    \code
+ *    // Set g3
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Set the ZKP public key for x3
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Set the ZKP proof for x3
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    // Set g4
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Set the ZKP public key for x4
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Set the ZKP proof for x4
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    \endcode
+ * -# To get the second round data that needs to be sent to the peer, call
+ *    \code
+ *    // Get A
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Get ZKP public key for x2*s
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Get ZKP proof for x2*s
+ *    psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    \endcode
+ * -# To provide the second round data received from the peer to the operation,
+ *    call
+ *    \code
+ *    // Set B
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...);
+ *    // Set ZKP public key for x4*s
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...);
+ *    // Set ZKP proof for x4*s
+ *    psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...);
+ *    \endcode
+ * -# To access the shared secret call
+ *    \code
+ *    // Get Ka=Kb=K
+ *    psa_pake_get_implicit_key()
+ *    \endcode
+ *
+ * For more information consult the documentation of the individual
+ * \c PSA_PAKE_STEP_XXX constants.
+ *
+ * At this point there is a cryptographic guarantee that only the authenticated
+ * party who used the same password is able to compute the key. But there is no
+ * guarantee that the peer is the party it claims to be and was able to do so.
+ *
+ * That is, the authentication is only implicit (the peer is not authenticated
+ * at this point, and no action should be taken that assume that they are - like
+ * for example accessing restricted files).
+ *
+ * To make the authentication explicit there are various methods, see Section 5
+ * of RFC 8236 for two examples.
+ *
+ */
+#define PSA_ALG_JPAKE                   ((psa_algorithm_t)0x0a000100)
+
+/** @} */
+
+/** \defgroup pake Password-authenticated key exchange (PAKE)
+ *
+ * This is a proposed PAKE interface for the PSA Crypto API. It is not part of
+ * the official PSA Crypto API yet.
+ *
+ * \note The content of this section is not part of the stable API and ABI
+ *       of Mbed Crypto and may change arbitrarily from version to version.
+ *       Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and
+ *       #PSA_ALG_JPAKE.
+ * @{
+ */
+
+/** \brief Encoding of the side of PAKE
+ *
+ * Encodes which side of the algorithm is being executed. For more information
+ * see the documentation of individual \c PSA_PAKE_SIDE_XXX constants.
+ */
+typedef uint8_t psa_pake_side_t;
+
+/** Encoding of input and output indicators for PAKE.
+ *
+ * Some PAKE algorithms need to exchange more data than just a single key share.
+ * This type is for encoding additional input and output data for such
+ * algorithms.
+ */
+typedef uint8_t psa_pake_step_t;
+
+/** Encoding of the type of the PAKE's primitive.
+ *
+ * Values defined by this standard will never be in the range 0x80-0xff.
+ * Vendors who define additional types must use an encoding in this range.
+ *
+ * For more information see the documentation of individual
+ * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.
+ */
+typedef uint8_t psa_pake_primitive_type_t;
+
+/** \brief Encoding of the family of the primitive associated with the PAKE.
+ *
+ * For more information see the documentation of individual
+ * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.
+ */
+typedef uint8_t psa_pake_family_t;
+
+/** \brief Encoding of the primitive associated with the PAKE.
+ *
+ * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro.
+ */
+typedef uint32_t psa_pake_primitive_t;
+
+/** The first peer in a balanced PAKE.
+ *
+ * Although balanced PAKE algorithms are symmetric, some of them needs an
+ * ordering of peers for the transcript calculations. If the algorithm does not
+ * need this, both #PSA_PAKE_SIDE_FIRST and #PSA_PAKE_SIDE_SECOND are
+ * accepted.
+ */
+#define PSA_PAKE_SIDE_FIRST                ((psa_pake_side_t)0x01)
+
+/** The second peer in a balanced PAKE.
+ *
+ * Although balanced PAKE algorithms are symmetric, some of them needs an
+ * ordering of peers for the transcript calculations. If the algorithm does not
+ * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are
+ * accepted.
+ */
+#define PSA_PAKE_SIDE_SECOND                ((psa_pake_side_t)0x02)
+
+/** The client in an augmented PAKE.
+ *
+ * Augmented PAKE algorithms need to differentiate between client and server.
+ */
+#define PSA_PAKE_SIDE_CLIENT                ((psa_pake_side_t)0x11)
+
+/** The server in an augmented PAKE.
+ *
+ * Augmented PAKE algorithms need to differentiate between client and server.
+ */
+#define PSA_PAKE_SIDE_SERVER                ((psa_pake_side_t)0x12)
+
+/** The PAKE primitive type indicating the use of elliptic curves.
+ *
+ * The values of the \c family and \c bits fields of the cipher suite identify a
+ * specific elliptic curve, using the same mapping that is used for ECC
+ * (::psa_ecc_family_t) keys.
+ *
+ * (Here \c family means the value returned by psa_pake_cs_get_family() and
+ * \c bits means the value returned by psa_pake_cs_get_bits().)
+ *
+ * Input and output during the operation can involve group elements and scalar
+ * values:
+ * -# The format for group elements is the same as for public keys on the
+ *  specific curve would be. For more information, consult the documentation of
+ *  psa_export_public_key().
+ * -# The format for scalars is the same as for private keys on the specific
+ *  curve would be. For more information, consult the documentation of
+ *  psa_export_key().
+ */
+#define PSA_PAKE_PRIMITIVE_TYPE_ECC       ((psa_pake_primitive_type_t)0x01)
+
+/** The PAKE primitive type indicating the use of Diffie-Hellman groups.
+ *
+ * The values of the \c family and \c bits fields of the cipher suite identify
+ * a specific Diffie-Hellman group, using the same mapping that is used for
+ * Diffie-Hellman (::psa_dh_family_t) keys.
+ *
+ * (Here \c family means the value returned by psa_pake_cs_get_family() and
+ * \c bits means the value returned by psa_pake_cs_get_bits().)
+ *
+ * Input and output during the operation can involve group elements and scalar
+ * values:
+ * -# The format for group elements is the same as for public keys on the
+ *  specific group would be. For more information, consult the documentation of
+ *  psa_export_public_key().
+ * -# The format for scalars is the same as for private keys on the specific
+ *  group would be. For more information, consult the documentation of
+ *  psa_export_key().
+ */
+#define PSA_PAKE_PRIMITIVE_TYPE_DH       ((psa_pake_primitive_type_t)0x02)
+
+/** Construct a PAKE primitive from type, family and bit-size.
+ *
+ * \param pake_type     The type of the primitive
+ *                      (value of type ::psa_pake_primitive_type_t).
+ * \param pake_family   The family of the primitive
+ *                      (the type and interpretation of this parameter depends
+ *                      on \p type, for more information consult the
+ *                      documentation of individual ::psa_pake_primitive_type_t
+ *                      constants).
+ * \param pake_bits     The bit-size of the primitive
+ *                      (Value of type \c size_t. The interpretation
+ *                      of this parameter depends on \p family, for more
+ *                      information consult the documentation of individual
+ *                      ::psa_pake_primitive_type_t constants).
+ *
+ * \return The constructed primitive value of type ::psa_pake_primitive_t.
+ *         Return 0 if the requested primitive can't be encoded as
+ *         ::psa_pake_primitive_t.
+ */
+#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \
+    ((pake_bits & 0xFFFF) != pake_bits) ? 0 :                 \
+    ((psa_pake_primitive_t) (((pake_type) << 24 |             \
+            (pake_family) << 16) | (pake_bits)))
+
+/** The key share being sent to or received from the peer.
+ *
+ * The format for both input and output at this step is the same as for public
+ * keys on the group determined by the primitive (::psa_pake_primitive_t) would
+ * be.
+ *
+ * For more information on the format, consult the documentation of
+ * psa_export_public_key().
+ *
+ * For information regarding how the group is determined, consult the
+ * documentation #PSA_PAKE_PRIMITIVE.
+ */
+#define PSA_PAKE_STEP_KEY_SHARE                 ((psa_pake_step_t)0x01)
+
+/** A Schnorr NIZKP public key.
+ *
+ * This is the ephemeral public key in the Schnorr Non-Interactive
+ * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235).
+ *
+ * The format for both input and output at this step is the same as for public
+ * keys on the group determined by the primitive (::psa_pake_primitive_t) would
+ * be.
+ *
+ * For more information on the format, consult the documentation of
+ * psa_export_public_key().
+ *
+ * For information regarding how the group is determined, consult the
+ * documentation #PSA_PAKE_PRIMITIVE.
+ */
+#define PSA_PAKE_STEP_ZK_PUBLIC                 ((psa_pake_step_t)0x02)
+
+/** A Schnorr NIZKP proof.
+ *
+ * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the
+ * value denoted by the letter 'r' in RFC 8235).
+ *
+ * Both for input and output, the value at this step is an integer less than
+ * the order of the group selected in the cipher suite. The format depends on
+ * the group as well:
+ *
+ * - For Montgomery curves, the encoding is little endian.
+ * - For everything else the encoding is big endian (see Section 2.3.8 of
+ *   _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf).
+ *
+ * In both cases leading zeroes are allowed as long as the length in bytes does
+ * not exceed the byte length of the group order.
+ *
+ * For information regarding how the group is determined, consult the
+ * documentation #PSA_PAKE_PRIMITIVE.
+ */
+#define PSA_PAKE_STEP_ZK_PROOF                  ((psa_pake_step_t)0x03)
+
+/** The type of the data strucure for PAKE cipher suites.
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice.
+ */
+typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t;
+
+/** Retrieve the PAKE 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 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 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 stored in the cipher suite structure.
+ */
+static psa_pake_primitive_t psa_pake_cs_get_primitive(
+                           const psa_pake_cipher_suite_t* cipher_suite
+                           );
+
+/** Declare the primitive for a PAKE cipher suite.
+ *
+ * This function overwrites any primitive 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 primitive            The primitive to write. If this is 0, the
+ *                             primitive type in \p cipher_suite becomes
+ *                             unspecified.
+ */
+static void psa_pake_cs_set_primitive(
+                           psa_pake_cipher_suite_t* cipher_suite,
+                           psa_pake_primitive_t primitive
+                           );
+
+/** 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. The return
+ *         value is 0 if the PAKE is not parametrised by a hash algorithm or if
+ *         the hash algorithm is not set.
+ */
+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.
+ *
+ * Before calling any function on a PAKE operation object, the application
+ * must initialize it by any of the following means:
+ * - Set the structure to all-bits-zero, for example:
+ *   \code
+ *   psa_pake_operation_t operation;
+ *   memset(&operation, 0, sizeof(operation));
+ *   \endcode
+ * - Initialize the structure to logical zero values, for example:
+ *   \code
+ *   psa_pake_operation_t operation = {0};
+ *   \endcode
+ * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT,
+ *   for example:
+ *   \code
+ *   psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT;
+ *   \endcode
+ * - Assign the result of the function psa_pake_operation_init()
+ *   to the structure, for example:
+ *   \code
+ *   psa_pake_operation_t operation;
+ *   operation = psa_pake_operation_init();
+ *   \endcode
+ *
+ * This is an implementation-defined \c struct. Applications should not
+ * make any assumptions about the content of this structure.
+ * Implementation details can change in future versions without notice. */
+typedef struct psa_pake_operation_s psa_pake_operation_t;
+
+/** Return an initial value for an PAKE operation object.
+ */
+static psa_pake_operation_t psa_pake_operation_init(void);
+
+/** Set the session information for a password-authenticated key exchange.
+ *
+ * The sequence of operations to set up a password-authenticated key exchange
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_pake_operation_t, e.g.
+ *    #PSA_PAKE_OPERATION_INIT.
+ * -# Call psa_pake_setup() to specify the cipher suite.
+ * -# Call \c psa_pake_set_xxx() functions on the operation to complete the
+ *    setup. The exact sequence of \c psa_pake_set_xxx() functions that needs
+ *    to be called depends on the algorithm in use.
+ *
+ * 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.
+ *
+ * A typical sequence of calls to perform a password-authenticated key
+ * exchange:
+ * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the
+ *    key share that needs to be sent to the peer.
+ * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide
+ *    the key share that was received from the peer.
+ * -# Depending on the algorithm additional calls to psa_pake_output() and
+ *    psa_pake_input() might be necessary.
+ * -# Call psa_pake_get_implicit_key() for accessing the shared secret.
+ *
+ * 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.
+ *
+ * If an error occurs at any step after a call to psa_pake_setup(),
+ * the operation will need to be reset by a call to psa_pake_abort(). The
+ * application may call psa_pake_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_pake_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A call to psa_pake_abort().
+ * - A successful call to psa_pake_get_implicit_key().
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized but not set up yet.
+ * \param cipher_suite          The cipher suite to use. (A cipher suite fully
+ *                              characterizes a PAKE algorithm and determines
+ *                              the algorithm as well.)
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The \p cipher_suite is not supported or is not valid.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_setup(psa_pake_operation_t *operation,
+                            psa_pake_cipher_suite_t cipher_suite);
+
+/** Set the password for a password-authenticated key exchange from key ID.
+ *
+ * Call this function when the password, or a value derived from the password,
+ * is already present in the key store.
+ *
+ * \param[in,out] operation     The operation object to set the password for. It
+ *                              must have been set up by psa_pake_setup() and
+ *                              not yet in use (neither psa_pake_output() nor
+ *                              psa_pake_input() has been called yet). It must
+ *                              be on operation for which the password hasn't
+ *                              been set yet (psa_pake_set_password_key()
+ *                              hasn't been called yet).
+ * \param password              Identifier of the key holding the password or a
+ *                              value derived from the password (eg. by a
+ *                              memory-hard function).  It must remain valid
+ *                              until the operation terminates. It must be of
+ *                              type #PSA_KEY_TYPE_PASSWORD or
+ *                              #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow
+ *                              the usage #PSA_KEY_USAGE_DERIVE.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must have been set up.)
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key is not compatible with the algorithm or the cipher suite.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation,
+                                       mbedtls_svc_key_id_t password);
+
+/** Set the user ID for a password-authenticated key exchange.
+ *
+ * Call this function to set the user ID. For PAKE algorithms that associate a
+ * user identifier with each side of the session you need to call
+ * psa_pake_set_peer() as well. For PAKE algorithms that associate a single
+ * user identifier with the session, call psa_pake_set_user() only.
+ *
+ * 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[in,out] operation     The operation object to set the user ID for. It
+ *                              must have been set up by psa_pake_setup() and
+ *                              not yet in use (neither psa_pake_output() nor
+ *                              psa_pake_input() has been called yet). It must
+ *                              be on operation for which the user ID hasn't
+ *                              been set (psa_pake_set_user() hasn't been
+ *                              called yet).
+ * \param[in] user_id           The user ID to authenticate with.
+ * \param user_id_len           Size of the \p user_id buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p user_id is NULL.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_set_user(psa_pake_operation_t *operation,
+                               const uint8_t *user_id,
+                               size_t user_id_len);
+
+/** Set the peer ID for a password-authenticated key exchange.
+ *
+ * Call this function in addition to psa_pake_set_user() for PAKE algorithms
+ * that associate a user identifier with each side of the session. For PAKE
+ * algorithms that associate a single user identifier with the session, call
+ * psa_pake_set_user() only.
+ *
+ * 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[in,out] operation     The operation object to set the peer ID for. It
+ *                              must have been set up by psa_pake_setup() and
+ *                              not yet in use (neither psa_pake_output() nor
+ *                              psa_pake_input() has been called yet). It must
+ *                              be on operation for which the peer ID hasn't
+ *                              been set (psa_pake_set_peer() hasn't been
+ *                              called yet).
+ * \param[in] peer_id           The peer's ID to authenticate.
+ * \param peer_id_len           Size of the \p peer_id buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The algorithm doesn't associate a second identity with the session.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p user_id is NULL.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation,
+                               const uint8_t *peer_id,
+                               size_t peer_id_len);
+
+/** Set the side for a password-authenticated key exchange.
+ *
+ * Not all PAKE algorithms need to differentiate the communicating entities.
+ * It is optional to call this function for PAKEs that don't require a side
+ * parameter. For such PAKEs the side parameter is ignored.
+ *
+ * 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[in,out] operation     The operation object to set the side for. It
+ *                              must have been set up by psa_pake_setup() and
+ *                              not yet in use (neither psa_pake_output() nor
+ *                              psa_pake_input() has been called yet). It must
+ *                              be on operation for which the side hasn't been
+ *                              set (psa_pake_set_side() hasn't been called
+ *                              yet).
+ * \param side                  A value of type ::psa_pake_side_t signaling the
+ *                              side of the algorithm that is being set up. For
+ *                              more information see the documentation of
+ *                              \c PSA_PAKE_SIDE_XXX constants.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The \p side for this algorithm is not supported or is not valid.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_set_side(psa_pake_operation_t *operation,
+                               psa_pake_side_t side);
+
+/** Get output for a step of a password-authenticated key exchange.
+ *
+ * Depending on the algorithm being executed, you might need to call this
+ * function several times or you might not need to call this at all.
+ *
+ * The exact sequence of calls to perform a password-authenticated key
+ * exchange depends on the algorithm in use.  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.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_pake_abort().
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param step                 The step of the algorithm for which the output is
+ *                             requested.
+ * \param[out] output          Buffer where the output is to be written in the
+ *                             format appropriate for this \p step. Refer to
+ *                             the documentation of the individual
+ *                             \c PSA_PAKE_STEP_XXX constants for more
+ *                             information.
+ * \param output_size          Size of the \p output buffer in bytes. This must
+ *                             be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c
+ *                             cipher_suite, \p type).
+ *
+ * \param[out] output_length   On success, the number of bytes of the returned
+ *                             output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active, but beyond that
+ *         validity is specific to the algorithm).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_output(psa_pake_operation_t *operation,
+                             psa_pake_step_t step,
+                             uint8_t *output,
+                             size_t output_size,
+                             size_t *output_length);
+
+/** Provide input for a step of a password-authenticated key exchange.
+ *
+ * Depending on the algorithm being executed, you might need to call this
+ * function several times or you might not need to call this at all.
+ *
+ * The exact sequence of calls to perform a password-authenticated key
+ * exchange depends on the algorithm in use.  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.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_pake_abort().
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param step                 The step for which the input is provided.
+ * \param[out] input           Buffer containing the input in the format
+ *                             appropriate for this \p step. Refer to the
+ *                             documentation of the individual
+ *                             \c PSA_PAKE_STEP_XXX constants for more
+ *                             information.
+ * \param[out] input_length    Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active, but beyond that
+ *         validity is specific to the algorithm).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The input is not valid for the algorithm, ciphersuite or \p step.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_input(psa_pake_operation_t *operation,
+                            psa_pake_step_t step,
+                            uint8_t *input,
+                            size_t input_length);
+
+/** Get implicitly confirmed shared secret from a PAKE.
+ *
+ * At this point there is a cryptographic guarantee that only the authenticated
+ * party who used the same password is able to compute the key. But there is no
+ * guarantee that the peer is the party it claims to be and was able to do so.
+ *
+ * That is, the authentication is only implicit. Since the peer is not
+ * authenticated yet, no action should be taken yet that assumes that the peer
+ * is who it claims to be. For example, do not access restricted files on the
+ * peer's behalf until an explicit authentication has succeeded.
+ *
+ * This function can be called after the key exchange phase of the operation
+ * has completed. It imports the shared secret output of the PAKE into the
+ * provided derivation operation. The input step
+ * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key
+ * material in the key derivation operation.
+ *
+ * The exact sequence of calls to perform a password-authenticated key
+ * exchange depends on the algorithm in use.  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.
+ *
+ * When this function returns successfully, \p operation becomes inactive.
+ * If this function returns an error status, both \p operation
+ * and \p key_derivation operations enter an error state and must be aborted by
+ * calling psa_pake_abort() and psa_key_derivation_abort() respectively.
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param[out] output          A key derivation operation that is ready
+ *                             for an input step of type
+ *                             #PSA_KEY_DERIVATION_INPUT_SECRET.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The PAKE operation state is not valid (it must be active, but beyond
+ *         that validity is specific to the algorithm).
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The state of \p output is not valid for
+ *         the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the
+ *         step is out of order or the application has done this step already
+ *         and it may not be repeated.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the output’s
+ *         algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation,
+                                       psa_key_derivation_operation_t *output);
+
+/**@}*/
+
+/** A sufficient output buffer size for psa_pake_output().
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_pake_output() will not fail due to an insufficient output buffer
+ * size. The actual size of the output might be smaller in any given call.
+ *
+ * See also #PSA_PAKE_OUTPUT_MAX_SIZE
+ *
+ * \param alg           A PAKE algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_PAKE(\p alg) is true).
+ * \param primitive     A primitive of type ::psa_pake_primitive_t that is
+ *                      compatible with algorithm \p alg.
+ * \param output_step   A value of type ::psa_pake_step_t that is valid for the
+ *                      algorithm \p alg.
+ * \return              A sufficient output buffer size for the specified
+ *                      output, cipher suite and algorithm. If the cipher suite,
+ *                      the output type or PAKE algorithm is not recognized, or
+ *                      the parameters are incompatible, return 0.
+ */
+#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0
+
+/** A sufficient input buffer size for psa_pake_input().
+ *
+ * The value returned by this macro is guaranteed to be large enough for any
+ * valid input to psa_pake_input() in an operation with the specified
+ * parameters.
+ *
+ * See also #PSA_PAKE_INPUT_MAX_SIZE
+ *
+ * \param alg           A PAKE algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_PAKE(\p alg) is true).
+ * \param primitive     A primitive of type ::psa_pake_primitive_t that is
+ *                      compatible with algorithm \p alg.
+ * \param input_step    A value of type ::psa_pake_step_t that is valid for the
+ *                      algorithm \p alg.
+ * \return              A sufficient input buffer size for the specified
+ *                      input, cipher suite and algorithm. If the cipher suite,
+ *                      the input type or PAKE algorithm is not recognized, or
+ *                      the parameters are incompatible, return 0.
+ */
+#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0
+
+/** Output buffer size for psa_pake_output() for any of the supported cipher
+ * suites and PAKE algorithms.
+ *
+ * This macro must expand to a compile-time constant integer.
+ *
+ * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output).
+ */
+#define PSA_PAKE_OUTPUT_MAX_SIZE 0
+
+/** Input buffer size for psa_pake_input() for any of the supported cipher
+ * suites and PAKE algorithms.
+ *
+ * This macro must expand to a compile-time constant integer.
+ *
+ * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p input).
+ */
+#define PSA_PAKE_INPUT_MAX_SIZE 0
+
+struct psa_pake_cipher_suite_s
+{
+    psa_algorithm_t algorithm;
+    psa_pake_primitive_type_t type;
+    psa_pake_family_t family;
+    uint16_t  bits;
+    psa_algorithm_t hash;
+};
+
+static inline psa_algorithm_t psa_pake_cs_get_algorithm(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return(cipher_suite->algorithm);
+}
+
+static inline void psa_pake_cs_set_algorithm(
+    psa_pake_cipher_suite_t *cipher_suite,
+    psa_algorithm_t algorithm)
+{
+    if(!PSA_ALG_IS_PAKE(algorithm))
+        cipher_suite->algorithm = 0;
+    else
+        cipher_suite->algorithm = algorithm;
+}
+
+static inline psa_pake_primitive_t psa_pake_cs_get_primitive(
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    return(PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family,
+                cipher_suite->bits));
+}
+
+static inline void psa_pake_cs_set_primitive(
+    psa_pake_cipher_suite_t *cipher_suite,
+    psa_pake_primitive_t primitive)
+{
+    cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24);
+    cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16));
+    cipher_suite->bits = (uint16_t) (0xFFFF & primitive);
+}
+
+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
+{
+    psa_algorithm_t alg;
+    union
+    {
+        /* Make the union non-empty even with no supported algorithms. */
+        uint8_t dummy;
+    } ctx;
+};
+
+/* This only zeroes out the first byte in the union, the rest is unspecified. */
+#define PSA_PAKE_OPERATION_INIT {0, {0}}
+static inline struct psa_pake_operation_s psa_pake_operation_init(void)
+{
+    const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT;
+    return(v);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
index 8acf22c..4787e44 100644
--- a/include/psa/crypto_platform.h
+++ b/include/psa/crypto_platform.h
@@ -32,14 +32,11 @@
 
 #ifndef PSA_CRYPTO_PLATFORM_H
 #define PSA_CRYPTO_PLATFORM_H
+#include "mbedtls/private_access.h"
 
 /* Include the Mbed TLS configuration file, the way Mbed TLS does it
  * in each of its header files. */
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "mbedtls/build_info.h"
 
 /* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx
  * feature symbols. */
@@ -81,6 +78,18 @@
 
 #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
+/*
+ * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM
+ * (Secure Partition Manager) integration which separates the code into two
+ * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing
+ * Environment). When building for the SPE, an additional header file should be
+ * included.
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_SPM)
+#define PSA_CRYPTO_SECURE 1
+#include "crypto_spe.h"
+#endif // MBEDTLS_PSA_CRYPTO_SPM
+
 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
 /** The type of the context passed to mbedtls_psa_external_get_random().
  *
@@ -92,7 +101,7 @@
  * are expected to replace it with a custom definition.
  */
 typedef struct {
-    uintptr_t opaque[2];
+    uintptr_t MBEDTLS_PRIVATE(opaque)[2];
 } mbedtls_psa_external_random_context_t;
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index 1dc8f9b..91a6d0b 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -33,6 +33,7 @@
  */
 #ifndef PSA_CRYPTO_SE_DRIVER_H
 #define PSA_CRYPTO_SE_DRIVER_H
+#include "mbedtls/private_access.h"
 
 #include "crypto_driver_common.h"
 
@@ -97,21 +98,21 @@
      * - psa_destroy_key() causes a call to
      *   psa_drv_se_key_management_t::p_destroy.
      */
-    const void *const persistent_data;
+    const void *const MBEDTLS_PRIVATE(persistent_data);
 
     /** The size of \c persistent_data in bytes.
      *
      * This is always equal to the value of the `persistent_data_size` field
      * of the ::psa_drv_se_t structure when the driver is registered.
      */
-    const size_t persistent_data_size;
+    const size_t MBEDTLS_PRIVATE(persistent_data_size);
 
     /** Driver transient data.
      *
      * The core initializes this value to 0 and does not read or modify it
      * afterwards. The driver may store whatever it wants in this field.
      */
-    uintptr_t transient_data;
+    uintptr_t MBEDTLS_PRIVATE(transient_data);
 } psa_drv_se_context_t;
 
 /** \brief A driver initialization function.
@@ -323,28 +324,28 @@
     /**The size in bytes of the hardware-specific secure element MAC context
      * structure
     */
-    size_t                    context_size;
+    size_t                    MBEDTLS_PRIVATE(context_size);
     /** Function that performs a MAC setup operation
      */
-    psa_drv_se_mac_setup_t          p_setup;
+    psa_drv_se_mac_setup_t          MBEDTLS_PRIVATE(p_setup);
     /** Function that performs a MAC update operation
      */
-    psa_drv_se_mac_update_t         p_update;
+    psa_drv_se_mac_update_t         MBEDTLS_PRIVATE(p_update);
     /** Function that completes a MAC operation
      */
-    psa_drv_se_mac_finish_t         p_finish;
+    psa_drv_se_mac_finish_t         MBEDTLS_PRIVATE(p_finish);
     /** Function that completes a MAC operation with a verify check
      */
-    psa_drv_se_mac_finish_verify_t  p_finish_verify;
+    psa_drv_se_mac_finish_verify_t  MBEDTLS_PRIVATE(p_finish_verify);
     /** Function that aborts a previoustly started MAC operation
      */
-    psa_drv_se_mac_abort_t          p_abort;
+    psa_drv_se_mac_abort_t          MBEDTLS_PRIVATE(p_abort);
     /** Function that performs a MAC operation in one call
      */
-    psa_drv_se_mac_generate_t       p_mac;
+    psa_drv_se_mac_generate_t       MBEDTLS_PRIVATE(p_mac);
     /** Function that performs a MAC and verify operation in one call
      */
-    psa_drv_se_mac_verify_t         p_mac_verify;
+    psa_drv_se_mac_verify_t         MBEDTLS_PRIVATE(p_mac_verify);
 } psa_drv_se_mac_t;
 /**@}*/
 
@@ -510,22 +511,22 @@
     /** The size in bytes of the hardware-specific secure element cipher
      * context structure
      */
-    size_t               context_size;
+    size_t               MBEDTLS_PRIVATE(context_size);
     /** Function that performs a cipher setup operation */
-    psa_drv_se_cipher_setup_t  p_setup;
+    psa_drv_se_cipher_setup_t  MBEDTLS_PRIVATE(p_setup);
     /** Function that sets a cipher IV (if necessary) */
-    psa_drv_se_cipher_set_iv_t p_set_iv;
+    psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv);
     /** Function that performs a cipher update operation */
-    psa_drv_se_cipher_update_t p_update;
+    psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update);
     /** Function that completes a cipher operation */
-    psa_drv_se_cipher_finish_t p_finish;
+    psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish);
     /** Function that aborts a cipher operation */
-    psa_drv_se_cipher_abort_t  p_abort;
+    psa_drv_se_cipher_abort_t  MBEDTLS_PRIVATE(p_abort);
     /** Function that performs ECB mode for a cipher operation
      * (Danger: ECB mode should not be used directly by clients of the PSA
      * Crypto Client API)
      */
-    psa_drv_se_cipher_ecb_t    p_ecb;
+    psa_drv_se_cipher_ecb_t    MBEDTLS_PRIVATE(p_ecb);
 } psa_drv_se_cipher_t;
 
 /**@}*/
@@ -681,13 +682,13 @@
  */
 typedef struct {
     /** Function that performs an asymmetric sign operation */
-    psa_drv_se_asymmetric_sign_t    p_sign;
+    psa_drv_se_asymmetric_sign_t    MBEDTLS_PRIVATE(p_sign);
     /** Function that performs an asymmetric verify operation */
-    psa_drv_se_asymmetric_verify_t  p_verify;
+    psa_drv_se_asymmetric_verify_t  MBEDTLS_PRIVATE(p_verify);
     /** Function that performs an asymmetric encrypt operation */
-    psa_drv_se_asymmetric_encrypt_t p_encrypt;
+    psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt);
     /** Function that performs an asymmetric decrypt operation */
-    psa_drv_se_asymmetric_decrypt_t p_decrypt;
+    psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt);
 } psa_drv_se_asymmetric_t;
 
 /**@}*/
@@ -798,9 +799,9 @@
  */
 typedef struct {
     /** Function that performs the AEAD encrypt operation */
-    psa_drv_se_aead_encrypt_t p_encrypt;
+    psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt);
     /** Function that performs the AEAD decrypt operation */
-    psa_drv_se_aead_decrypt_t p_decrypt;
+    psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt);
 } psa_drv_se_aead_t;
 /**@}*/
 
@@ -1120,19 +1121,19 @@
  */
 typedef struct {
     /** Function that allocates a slot for a key. */
-    psa_drv_se_allocate_key_t   p_allocate;
+    psa_drv_se_allocate_key_t   MBEDTLS_PRIVATE(p_allocate);
     /** Function that checks the validity of a slot for a key. */
-    psa_drv_se_validate_slot_number_t p_validate_slot_number;
+    psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number);
     /** Function that performs a key import operation */
-    psa_drv_se_import_key_t     p_import;
+    psa_drv_se_import_key_t     MBEDTLS_PRIVATE(p_import);
     /** Function that performs a generation */
-    psa_drv_se_generate_key_t   p_generate;
+    psa_drv_se_generate_key_t   MBEDTLS_PRIVATE(p_generate);
     /** Function that performs a key destroy operation */
-    psa_drv_se_destroy_key_t    p_destroy;
+    psa_drv_se_destroy_key_t    MBEDTLS_PRIVATE(p_destroy);
     /** Function that performs a key export operation */
-    psa_drv_se_export_key_t     p_export;
+    psa_drv_se_export_key_t     MBEDTLS_PRIVATE(p_export);
     /** Function that performs a public key export operation */
-    psa_drv_se_export_key_t     p_export_public;
+    psa_drv_se_export_key_t     MBEDTLS_PRIVATE(p_export_public);
 } psa_drv_se_key_management_t;
 
 /**@}*/
@@ -1263,16 +1264,16 @@
  */
 typedef struct {
     /** The driver-specific size of the key derivation context */
-    size_t                           context_size;
+    size_t                           MBEDTLS_PRIVATE(context_size);
     /** Function that performs a key derivation setup */
-    psa_drv_se_key_derivation_setup_t      p_setup;
+    psa_drv_se_key_derivation_setup_t      MBEDTLS_PRIVATE(p_setup);
     /** Function that sets key derivation collateral */
-    psa_drv_se_key_derivation_collateral_t p_collateral;
+    psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral);
     /** Function that performs a final key derivation step */
-    psa_drv_se_key_derivation_derive_t     p_derive;
+    psa_drv_se_key_derivation_derive_t     MBEDTLS_PRIVATE(p_derive);
     /** Function that perforsm a final key derivation or agreement and
      * exports the key */
-    psa_drv_se_key_derivation_export_t     p_export;
+    psa_drv_se_key_derivation_export_t     MBEDTLS_PRIVATE(p_export);
 } psa_drv_se_key_derivation_t;
 
 /**@}*/
@@ -1293,7 +1294,7 @@
      * a different version of this specification.
      * Use #PSA_DRV_SE_HAL_VERSION.
      */
-    uint32_t hal_version;
+    uint32_t MBEDTLS_PRIVATE(hal_version);
 
     /** The size of the driver's persistent data in bytes.
      *
@@ -1303,7 +1304,7 @@
      * for more information about why and how a driver can use
      * persistent data.
      */
-    size_t persistent_data_size;
+    size_t MBEDTLS_PRIVATE(persistent_data_size);
 
     /** The driver initialization function.
      *
@@ -1315,14 +1316,14 @@
      * If this field is \c NULL, it is equivalent to a function that does
      * nothing and returns #PSA_SUCCESS.
      */
-    psa_drv_se_init_t p_init;
+    psa_drv_se_init_t MBEDTLS_PRIVATE(p_init);
 
-    const psa_drv_se_key_management_t *key_management;
-    const psa_drv_se_mac_t *mac;
-    const psa_drv_se_cipher_t *cipher;
-    const psa_drv_se_aead_t *aead;
-    const psa_drv_se_asymmetric_t *asymmetric;
-    const psa_drv_se_key_derivation_t *derivation;
+    const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management);
+    const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac);
+    const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher);
+    const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead);
+    const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric);
+    const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation);
 } psa_drv_se_t;
 
 /** The current version of the secure element driver HAL.
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
index 79f9673..4c67f10 100644
--- a/include/psa/crypto_sizes.h
+++ b/include/psa/crypto_sizes.h
@@ -42,11 +42,7 @@
 
 /* Include the Mbed TLS configuration file, the way Mbed TLS does it
  * in each of its header files. */
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "mbedtls/build_info.h"
 
 #define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8)
 #define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8)
@@ -68,8 +64,6 @@
  */
 #define PSA_HASH_LENGTH(alg)                                        \
     (                                                               \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 :            \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 :            \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 :            \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 :      \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 :          \
@@ -998,9 +992,10 @@
  */
 #define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length)             \
     (alg == PSA_ALG_CBC_PKCS7 ?                                                 \
+     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                            \
      PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type),          \
                               (input_length) + 1) +                             \
-     PSA_CIPHER_IV_LENGTH((key_type), (alg)) :                                  \
+     PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0) :                             \
      (PSA_ALG_IS_CIPHER(alg) ?                                                  \
       (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) :                \
      0))
@@ -1079,12 +1074,13 @@
  */
 #define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)              \
     (PSA_ALG_IS_CIPHER(alg) ?                                                   \
+    (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                             \
      (((alg) == PSA_ALG_CBC_PKCS7      ||                                       \
        (alg) == PSA_ALG_CBC_NO_PADDING ||                                       \
        (alg) == PSA_ALG_ECB_NO_PADDING) ?                                       \
       PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type),         \
                                 input_length) :                                 \
-      (input_length)) :                                                         \
+      (input_length)) : 0) :                                                    \
      0)
 
 /** A sufficient output buffer size for psa_cipher_update(), for any of the
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index e05c846..4b1195d 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -60,6 +60,7 @@
 
 #ifndef PSA_CRYPTO_STRUCT_H
 #define PSA_CRYPTO_STRUCT_H
+#include "mbedtls/private_access.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -67,11 +68,7 @@
 
 /* Include the Mbed TLS configuration file, the way Mbed TLS does it
  * in each of its header files. */
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "mbedtls/build_info.h"
 
 #include "mbedtls/cmac.h"
 #include "mbedtls/gcm.h"
@@ -90,11 +87,11 @@
      * ID values are auto-generated in psa_driver_wrappers.h.
      * ID value zero means the context is not valid or not assigned to
      * any driver (i.e. the driver context is not active, in use). */
-    unsigned int id;
-    psa_driver_hash_context_t ctx;
+    unsigned int MBEDTLS_PRIVATE(id);
+    psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx);
 };
 
-#define PSA_HASH_OPERATION_INIT {0, {0}}
+#define PSA_HASH_OPERATION_INIT { 0, { 0 } }
 static inline struct psa_hash_operation_s psa_hash_operation_init( void )
 {
     const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;
@@ -109,17 +106,17 @@
      * ID values are auto-generated in psa_crypto_driver_wrappers.h
      * ID value zero means the context is not valid or not assigned to
      * any driver (i.e. none of the driver contexts are active). */
-    unsigned int id;
+    unsigned int MBEDTLS_PRIVATE(id);
 
-    unsigned int iv_required : 1;
-    unsigned int iv_set : 1;
+    unsigned int MBEDTLS_PRIVATE(iv_required) : 1;
+    unsigned int MBEDTLS_PRIVATE(iv_set) : 1;
 
-    uint8_t default_iv_length;
+    uint8_t MBEDTLS_PRIVATE(default_iv_length);
 
-    psa_driver_cipher_context_t ctx;
+    psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx);
 };
 
-#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, {0}}
+#define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } }
 static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
 {
     const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
@@ -138,13 +135,13 @@
      * ID values are auto-generated in psa_driver_wrappers.h
      * ID value zero means the context is not valid or not assigned to
      * any driver (i.e. none of the driver contexts are active). */
-    unsigned int id;
-    uint8_t mac_size;
-    unsigned int is_sign : 1;
-    psa_driver_mac_context_t ctx;
+    unsigned int MBEDTLS_PRIVATE(id);
+    uint8_t MBEDTLS_PRIVATE(mac_size);
+    unsigned int MBEDTLS_PRIVATE(is_sign) : 1;
+    psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx);
 };
 
-#define PSA_MAC_OPERATION_INIT {0, 0, 0, {0}}
+#define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } }
 static inline struct psa_mac_operation_s psa_mac_operation_init( void )
 {
     const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
@@ -162,19 +159,19 @@
      * any driver (i.e. none of the driver contexts are active). */
     unsigned int id;
 
-    psa_algorithm_t alg;
-    psa_key_type_t key_type;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    psa_key_type_t MBEDTLS_PRIVATE(key_type);
 
-    size_t ad_remaining;
-    size_t body_remaining;
+    size_t MBEDTLS_PRIVATE(ad_remaining);
+    size_t MBEDTLS_PRIVATE(body_remaining);
 
-    unsigned int nonce_set : 1;
-    unsigned int lengths_set : 1;
-    unsigned int ad_started : 1;
-    unsigned int body_started : 1;
-    unsigned int is_encrypt : 1;
+    unsigned int MBEDTLS_PRIVATE(nonce_set) : 1;
+    unsigned int MBEDTLS_PRIVATE(lengths_set) : 1;
+    unsigned int MBEDTLS_PRIVATE(ad_started) : 1;
+    unsigned int MBEDTLS_PRIVATE(body_started) : 1;
+    unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;
 
-    psa_driver_aead_context_t ctx;
+    psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx);
 };
 
 #define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}}
@@ -187,18 +184,18 @@
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
 typedef struct
 {
-    uint8_t *info;
-    size_t info_length;
-    psa_mac_operation_t hmac;
-    uint8_t prk[PSA_HASH_MAX_SIZE];
-    uint8_t output_block[PSA_HASH_MAX_SIZE];
+    uint8_t *MBEDTLS_PRIVATE(info);
+    size_t MBEDTLS_PRIVATE(info_length);
+    psa_mac_operation_t MBEDTLS_PRIVATE(hmac);
+    uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE];
+    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
 #if PSA_HASH_MAX_SIZE > 0xff
 #error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
 #endif
-    uint8_t offset_in_block;
-    uint8_t block_number;
-    unsigned int state : 2;
-    unsigned int info_set : 1;
+    uint8_t MBEDTLS_PRIVATE(offset_in_block);
+    uint8_t MBEDTLS_PRIVATE(block_number);
+    unsigned int MBEDTLS_PRIVATE(state) : 2;
+    unsigned int MBEDTLS_PRIVATE(info_set) : 1;
 } psa_hkdf_key_derivation_t;
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
@@ -221,50 +218,51 @@
 
     /* Indicates how many bytes in the current HMAC block have
      * not yet been read by the user. */
-    uint8_t left_in_block;
+    uint8_t MBEDTLS_PRIVATE(left_in_block);
 
     /* The 1-based number of the block. */
-    uint8_t block_number;
+    uint8_t MBEDTLS_PRIVATE(block_number);
 
-    psa_tls12_prf_key_derivation_state_t state;
+    psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state);
 
-    uint8_t *secret;
-    size_t secret_length;
-    uint8_t *seed;
-    size_t seed_length;
-    uint8_t *label;
-    size_t label_length;
+    uint8_t *MBEDTLS_PRIVATE(secret);
+    size_t MBEDTLS_PRIVATE(secret_length);
+    uint8_t *MBEDTLS_PRIVATE(seed);
+    size_t MBEDTLS_PRIVATE(seed_length);
+    uint8_t *MBEDTLS_PRIVATE(label);
+    size_t MBEDTLS_PRIVATE(label_length);
 
-    uint8_t Ai[PSA_HASH_MAX_SIZE];
+    uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE];
 
-    /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
-    uint8_t output_block[PSA_HASH_MAX_SIZE];
+    /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */
+    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
 } psa_tls12_prf_key_derivation_t;
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
 struct psa_key_derivation_s
 {
-    psa_algorithm_t alg;
-    unsigned int can_output_key : 1;
-    size_t capacity;
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    unsigned int MBEDTLS_PRIVATE(can_output_key) : 1;
+    size_t MBEDTLS_PRIVATE(capacity);
     union
     {
         /* Make the union non-empty even with no supported algorithms. */
-        uint8_t dummy;
+        uint8_t MBEDTLS_PRIVATE(dummy);
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
-        psa_hkdf_key_derivation_t hkdf;
+        psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf);
 #endif
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
-        psa_tls12_prf_key_derivation_t tls12_prf;
+        psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf);
 #endif
-    } ctx;
+    } MBEDTLS_PRIVATE(ctx);
 };
 
 /* This only zeroes out the first byte in the union, the rest is unspecified. */
-#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}}
-static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void )
+#define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } }
+static inline struct psa_key_derivation_s psa_key_derivation_operation_init(
+        void )
 {
     const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT;
     return( v );
@@ -272,13 +270,13 @@
 
 struct psa_key_policy_s
 {
-    psa_key_usage_t usage;
-    psa_algorithm_t alg;
-    psa_algorithm_t alg2;
+    psa_key_usage_t MBEDTLS_PRIVATE(usage);
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    psa_algorithm_t MBEDTLS_PRIVATE(alg2);
 };
 typedef struct psa_key_policy_s psa_key_policy_t;
 
-#define PSA_KEY_POLICY_INIT {0, 0, 0}
+#define PSA_KEY_POLICY_INIT { 0, 0, 0 }
 static inline struct psa_key_policy_s psa_key_policy_init( void )
 {
     const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;
@@ -290,7 +288,7 @@
 typedef uint16_t psa_key_bits_t;
 /* The maximum value of the type used to represent bit-sizes.
  * This is used to mark an invalid key size. */
-#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) )
+#define PSA_KEY_BITS_TOO_LARGE          ( ( psa_key_bits_t ) -1 )
 /* The maximum size of a key in bits.
  * Currently defined as the maximum that can be represented, rounded down
  * to a whole number of bytes.
@@ -323,30 +321,33 @@
 
 typedef struct
 {
-    psa_key_type_t type;
-    psa_key_bits_t bits;
-    psa_key_lifetime_t lifetime;
-    mbedtls_svc_key_id_t id;
-    psa_key_policy_t policy;
-    psa_key_attributes_flag_t flags;
+    psa_key_type_t MBEDTLS_PRIVATE(type);
+    psa_key_bits_t MBEDTLS_PRIVATE(bits);
+    psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime);
+    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id);
+    psa_key_policy_t MBEDTLS_PRIVATE(policy);
+    psa_key_attributes_flag_t MBEDTLS_PRIVATE(flags);
 } psa_core_key_attributes_t;
 
-#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, MBEDTLS_SVC_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0}
+#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0,            \
+                                       PSA_KEY_LIFETIME_VOLATILE,       \
+                                       MBEDTLS_SVC_KEY_ID_INIT,         \
+                                       PSA_KEY_POLICY_INIT, 0 }
 
 struct psa_key_attributes_s
 {
-    psa_core_key_attributes_t core;
+    psa_core_key_attributes_t MBEDTLS_PRIVATE(core);
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    psa_key_slot_number_t slot_number;
+    psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number);
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    void *domain_parameters;
-    size_t domain_parameters_size;
+    void *MBEDTLS_PRIVATE(domain_parameters);
+    size_t MBEDTLS_PRIVATE(domain_parameters_size);
 };
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0}
+#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0 }
 #else
-#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
+#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0 }
 #endif
 
 static inline struct psa_key_attributes_s psa_key_attributes_init( void )
@@ -358,13 +359,13 @@
 static inline void psa_set_key_id( psa_key_attributes_t *attributes,
                                    mbedtls_svc_key_id_t key )
 {
-    psa_key_lifetime_t lifetime = attributes->core.lifetime;
+    psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime);
 
-    attributes->core.id = key;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = key;
 
     if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
     {
-        attributes->core.lifetime =
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) =
             PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
                 PSA_KEY_LIFETIME_PERSISTENT,
                 PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) );
@@ -372,77 +373,87 @@
 }
 
 static inline mbedtls_svc_key_id_t psa_get_key_id(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.id );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) );
 }
 
 #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
 static inline void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes,
                                              mbedtls_key_owner_id_t owner )
 {
-    attributes->core.id.owner = owner;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner;
 }
 #endif
 
-static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
-                                        psa_key_lifetime_t lifetime)
+static inline void psa_set_key_lifetime( psa_key_attributes_t *attributes,
+                                        psa_key_lifetime_t lifetime )
 {
-    attributes->core.lifetime = lifetime;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = lifetime;
     if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
     {
 #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
-        attributes->core.id.key_id = 0;
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0;
 #else
-        attributes->core.id = 0;
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = 0;
 #endif
     }
 }
 
 static inline psa_key_lifetime_t psa_get_key_lifetime(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.lifetime );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) );
+}
+
+static inline void psa_extend_key_usage_flags( psa_key_usage_t *usage_flags )
+{
+    if( *usage_flags & PSA_KEY_USAGE_SIGN_HASH )
+        *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE;
+
+    if( *usage_flags & PSA_KEY_USAGE_VERIFY_HASH )
+        *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE;
 }
 
 static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
                                            psa_key_usage_t usage_flags)
 {
-    attributes->core.policy.usage = usage_flags;
+    psa_extend_key_usage_flags( &usage_flags );
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags;
 }
 
 static inline psa_key_usage_t psa_get_key_usage_flags(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.policy.usage );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) );
 }
 
-static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
-                                         psa_algorithm_t alg)
+static inline void psa_set_key_algorithm( psa_key_attributes_t *attributes,
+                                         psa_algorithm_t alg )
 {
-    attributes->core.policy.alg = alg;
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg;
 }
 
 static inline psa_algorithm_t psa_get_key_algorithm(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.policy.alg );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) );
 }
 
 /* This function is declared in crypto_extra.h, which comes after this
  * header file, but we need the function here, so repeat the declaration. */
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
+psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes,
                                            psa_key_type_t type,
                                            const uint8_t *data,
-                                           size_t data_length);
+                                           size_t data_length );
 
-static inline void psa_set_key_type(psa_key_attributes_t *attributes,
-                                    psa_key_type_t type)
+static inline void psa_set_key_type( psa_key_attributes_t *attributes,
+                                    psa_key_type_t type )
 {
-    if( attributes->domain_parameters == NULL )
+    if( attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL )
     {
         /* Common case: quick path */
-        attributes->core.type = type;
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
     }
     else
     {
@@ -455,24 +466,24 @@
 }
 
 static inline psa_key_type_t psa_get_key_type(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.type );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) );
 }
 
-static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
-                                    size_t bits)
+static inline void psa_set_key_bits( psa_key_attributes_t *attributes,
+                                    size_t bits )
 {
     if( bits > PSA_MAX_KEY_BITS )
-        attributes->core.bits = PSA_KEY_BITS_TOO_LARGE;
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE;
     else
-        attributes->core.bits = (psa_key_bits_t) bits;
+        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits;
 }
 
 static inline size_t psa_get_key_bits(
-    const psa_key_attributes_t *attributes)
+    const psa_key_attributes_t *attributes )
 {
-    return( attributes->core.bits );
+    return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) );
 }
 
 #ifdef __cplusplus
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 386c7d7..2cf965d 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -32,6 +32,7 @@
 
 #ifndef PSA_CRYPTO_TYPES_H
 #define PSA_CRYPTO_TYPES_H
+#include "mbedtls/private_access.h"
 
 #include "crypto_platform.h"
 
@@ -234,8 +235,8 @@
  */
 typedef struct
 {
-    psa_key_id_t key_id;
-    mbedtls_key_owner_id_t owner;
+    psa_key_id_t MBEDTLS_PRIVATE(key_id);
+    mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner);
 } mbedtls_svc_key_id_t;
 
 #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 497bd8f..daef941 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -33,6 +33,7 @@
 
 #ifndef PSA_CRYPTO_VALUES_H
 #define PSA_CRYPTO_VALUES_H
+#include "mbedtls/private_access.h"
 
 /** \defgroup error Error codes
  * @{
@@ -480,12 +481,6 @@
  * Camellia block cipher. */
 #define PSA_KEY_TYPE_CAMELLIA                       ((psa_key_type_t)0x2403)
 
-/** Key for the RC4 stream cipher.
- *
- * Note that RC4 is weak and deprecated and should only be used in
- * legacy protocols. */
-#define PSA_KEY_TYPE_ARC4                           ((psa_key_type_t)0x2002)
-
 /** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm.
  *
  * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539.
@@ -840,7 +835,7 @@
  *
  * \param alg An algorithm identifier (value of type #psa_algorithm_t).
  *
- * \return 1 if \p alg is a key stretching / passowrd hashing algorithm, 0
+ * \return 1 if \p alg is a key stretching / password hashing algorithm, 0
  *         otherwise. This macro may return either 0 or 1 if \p alg is not a
  *         supported algorithm identifier.
  */
@@ -849,10 +844,6 @@
      (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG)
 
 #define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
-/** MD2 */
-#define PSA_ALG_MD2                             ((psa_algorithm_t)0x02000001)
-/** MD4 */
-#define PSA_ALG_MD4                             ((psa_algorithm_t)0x02000002)
 /** MD5 */
 #define PSA_ALG_MD5                             ((psa_algorithm_t)0x02000003)
 /** PSA_ALG_RIPEMD160 */
@@ -1114,7 +1105,6 @@
  *
  * The underlying stream cipher is determined by the key type.
  * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20.
- * - To use ARC4, use a key type of #PSA_KEY_TYPE_ARC4.
  */
 #define PSA_ALG_STREAM_CIPHER                   ((psa_algorithm_t)0x04800100)
 
@@ -2030,6 +2020,27 @@
     (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \
      PSA_KEY_PERSISTENCE_VOLATILE)
 
+/** Whether a key lifetime indicates that the key is read-only.
+ *
+ * Read-only keys cannot be created or destroyed through the PSA Crypto API.
+ * They must be created through platform-specific means that bypass the API.
+ *
+ * Some platforms may offer ways to destroy read-only keys. For example,
+ * consider a platform with multiple levels of privilege, where a
+ * low-privilege application can use a key but is not allowed to destroy
+ * it, and the platform exposes the key to the application with a read-only
+ * lifetime. High-privilege code can destroy the key even though the
+ * application sees the key as read-only.
+ *
+ * \param lifetime      The lifetime value to query (value of type
+ *                      ::psa_key_lifetime_t).
+ *
+ * \return \c 1 if the key is read-only, otherwise \c 0.
+ */
+#define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)  \
+    (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \
+     PSA_KEY_PERSISTENCE_READ_ONLY)
+
 /** Construct a lifetime from a persistence level and a location.
  *
  * \param persistence   The persistence level
@@ -2124,8 +2135,8 @@
 static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make(
     mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id )
 {
-    return( (mbedtls_svc_key_id_t){ .key_id = key_id,
-                                    .owner = owner_id } );
+    return( (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id,
+                                    .MBEDTLS_PRIVATE(owner) = owner_id } );
 }
 
 /** Compare two key identifiers.
@@ -2138,8 +2149,8 @@
 static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1,
                                             mbedtls_svc_key_id_t id2 )
 {
-    return( ( id1.key_id == id2.key_id ) &&
-            mbedtls_key_owner_id_equal( id1.owner, id2.owner ) );
+    return( ( id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id) ) &&
+            mbedtls_key_owner_id_equal( id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner) ) );
 }
 
 /** Check whether a key identifier is null.
@@ -2150,7 +2161,7 @@
  */
 static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key )
 {
-    return( ( key.key_id == 0 ) && ( key.owner == 0 ) );
+    return( key.MBEDTLS_PRIVATE(key_id) == 0 );
 }
 
 #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
@@ -2255,12 +2266,14 @@
 /** Whether the key may be used to derive other keys or produce a password
  * hash.
  *
- * This flag allows the key to be used as the input of
- * psa_key_derivation_input_key() at the step
- * #PSA_KEY_DERIVATION_INPUT_SECRET of #PSA_KEY_DERIVATION_INPUT_PASSWORD
- * depending on the algorithm, and allows the use of
- * psa_key_derivation_output_bytes() or psa_key_derivation_output_key()
- * at the end of the operation.
+ * This flag allows the key to be used for a key derivation operation or for
+ * a key agreement operation, if otherwise permitted by by the key's type and
+ * policy.
+ *
+ * If this flag is present on all keys used in calls to
+ * psa_key_derivation_input_key() for a key derivation operation, then it
+ * permits calling psa_key_derivation_output_bytes() or
+ * psa_key_derivation_output_key() at the end of the operation.
  */
 #define PSA_KEY_USAGE_DERIVE                    ((psa_key_usage_t)0x00004000)
 
@@ -2269,14 +2282,13 @@
  *
  * This flag allows the key to be used:
  *
- * - for a key of type #PSA_KEY_TYPE_PASSWORD_HASH, as the \c key argument of
- *   psa_key_derivation_verify_key();
- * - for a key of type #PSA_KEY_TYPE_PASSWORD (or #PSA_KEY_TYPE_DERIVE), as
- *   the input to psa_key_derivation_input_key() at the step
- *   #PSA_KEY_DERIVATION_INPUT_PASSWORD (or #PSA_KEY_DERIVATION_INPUT_SECRET);
- *   then at the end of the operation use of psa_key_derivation_verify_bytes()
- *   or psa_key_derivation_verify_key() will be permitted (but not
- *   psa_key_derivation_output_xxx() unless #PSA_KEY_USAGE_DERIVE is set).
+ * This flag allows the key to be used in a key derivation operation, if
+ * otherwise permitted by by the key's type and policy.
+ *
+ * If this flag is present on all keys used in calls to
+ * psa_key_derivation_input_key() for a key derivation operation, then it
+ * permits calling psa_key_derivation_verify_bytes() or
+ * psa_key_derivation_verify_key() at the end of the operation.
  */
 #define PSA_KEY_USAGE_VERIFY_DERIVATION         ((psa_key_usage_t)0x00008000)
 
@@ -2295,11 +2307,11 @@
  *
  * The secret can also be a direct input (passed to
  * key_derivation_input_bytes()). In this case, the derivation operation
- * may not be used to derive or verify keys: the operation will only allow
- * psa_key_derivation_output_bytes() or
- * psa_key_derivation_verify_bytes() but not
- * psa_key_derivation_output_key() or
- * psa_key_derivation_verify_key().
+ * may not be used to derive keys: the operation will only allow
+ * psa_key_derivation_output_bytes(),
+ * psa_key_derivation_verify_bytes(), or
+ * psa_key_derivation_verify_key(), but not
+ * psa_key_derivation_output_key().
  */
 #define PSA_KEY_DERIVATION_INPUT_SECRET     ((psa_key_derivation_step_t)0x0101)
 
@@ -2313,11 +2325,11 @@
  *
  * The secret can also be a direct input (passed to
  * key_derivation_input_bytes()). In this case, the derivation operation
- * may not be used to derive or verify keys: the operation will only allow
- * psa_key_derivation_output_bytes() or
- * psa_key_derivation_verify_bytes(), not
- * psa_key_derivation_output_key() or
- * psa_key_derivation_verify_key().
+ * may not be used to derive keys: the operation will only allow
+ * psa_key_derivation_output_bytes(),
+ * psa_key_derivation_verify_bytes(), or
+ * psa_key_derivation_verify_key(), but not
+ * psa_key_derivation_output_key().
  */
 #define PSA_KEY_DERIVATION_INPUT_PASSWORD   ((psa_key_derivation_step_t)0x0102)