Merge pull request #4473 from tniessen/typos-in-header-files

Fix typos in C header files
diff --git a/ChangeLog.d/posix-define.txt b/ChangeLog.d/posix-define.txt
new file mode 100644
index 0000000..98cf2d0
--- /dev/null
+++ b/ChangeLog.d/posix-define.txt
@@ -0,0 +1,6 @@
+Bugfix
+   * In library/net_sockets.c, _POSIX_C_SOURCE and _XOPEN_SOURCE are
+     defined to specific values.  If the code is used in a context
+     where these are already defined, this can result in a compilation
+     error.  Instead, assume that if they are defined, the values will
+     be adequate to build Mbed TLS.
diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md
index 23274c7..125a415 100644
--- a/docs/proposed/psa-driver-interface.md
+++ b/docs/proposed/psa-driver-interface.md
@@ -305,9 +305,12 @@
 * `"key_derivation_setup"`: called by `psa_key_derivation_setup()`.
 * `"key_derivation_set_capacity"`: called by `psa_key_derivation_set_capacity()`. The core will always enforce the capacity, therefore this function does not need to do anything for algorithms where the output stream only depends on the effective generated length and not on the capacity.
 * `"key_derivation_input_bytes"`: called by `psa_key_derivation_input_bytes()` and `psa_key_derivation_input_key()`. For transparent drivers, when processing a call to `psa_key_derivation_input_key()`, the core always calls the applicable driver's `"key_derivation_input_bytes"` entry point.
+* `"key_derivation_input_integer"`: called by `psa_key_derivation_input_integer()`.
 * `"key_derivation_input_key"` (opaque drivers only)
 * `"key_derivation_output_bytes"`: called by `psa_key_derivation_output_bytes()`; also by `psa_key_derivation_output_key()` for transparent drivers.
 * `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()` for transparent drivers when deriving an asymmetric key pair, and also for opaque drivers.
+* `"key_derivation_verify_bytes"` (opaque drivers only).
+* `"key_derivation_verify_key"` (opaque drivers only).
 * `"key_derivation_abort"`: called by all key derivation functions of the PSA Cryptography API.
 
 TODO: key input and output for opaque drivers; deterministic key generation for transparent drivers
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 94b8f99..b14f4c5 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -3337,6 +3337,50 @@
     const uint8_t *data,
     size_t data_length);
 
+/** Provide a numeric input for key derivation or key agreement.
+ *
+ * Which inputs are required and in what order depends on the algorithm.
+ * However, when an algorithm requires a particular order, numeric inputs
+ * usually come first as they tend to be configuration parameters.
+ * Refer to the documentation of each key derivation or key agreement
+ * algorithm for information.
+ *
+ * This function is used for inputs which are fixed-size non-negative
+ * integers.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_key_derivation_abort().
+ *
+ * \param[in,out] operation       The key derivation operation object to use.
+ *                                It must have been set up with
+ *                                psa_key_derivation_setup() and must not
+ *                                have produced any output yet.
+ * \param step                    Which step the input data is for.
+ * \param[in] value               The value of the numeric input.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c step is not compatible with the operation's algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c step does not allow numeric inputs.
+ * \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 operation state is not valid for this input \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_key_derivation_input_integer(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    uint64_t value);
+
 /** Provide an input for key derivation in the form of a key.
  *
  * Which inputs are required and in what order depends on the algorithm.
@@ -3361,12 +3405,29 @@
  * \param step                    Which step the input data is for.
  * \param key                     Identifier of the key. It must have an
  *                                appropriate type for step and must allow the
- *                                usage #PSA_KEY_USAGE_DERIVE.
+ *                                usage #PSA_KEY_USAGE_DERIVE or
+ *                                #PSA_KEY_USAGE_VERIFY_DERIVATION (see note)
+ *                                and the algorithm used by the operation.
+ *
+ * \note Once all inputs steps are completed, the operations will allow:
+ * - psa_key_derivation_output_bytes() if each input was either a direct input
+ *   or  a key with #PSA_KEY_USAGE_DERIVE set;
+ * - psa_key_derivation_output_key() if the input for step
+ *   #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
+ *   was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
+ *   either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;
+ * - psa_key_derivation_verify_bytes() if each input was either a direct input
+ *   or  a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set;
+ * - psa_key_derivation_verify_key() under the same conditions as
+ *   psa_key_derivation_verify_bytes().
  *
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key allows neither #PSA_KEY_USAGE_DERIVE nor
+ *         #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this
+ *         algorithm.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \c step is not compatible with the operation's algorithm.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -3479,6 +3540,9 @@
  * \param output_length     Number of bytes to output.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         One of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_DERIVE.
  * \retval #PSA_ERROR_INSUFFICIENT_DATA
  *                          The operation's capacity was less than
  *                          \p output_length bytes. Note that in this case,
@@ -3539,7 +3603,8 @@
  *     - #PSA_KEY_TYPE_ARC4;
  *     - #PSA_KEY_TYPE_CAMELLIA;
  *     - #PSA_KEY_TYPE_DERIVE;
- *     - #PSA_KEY_TYPE_HMAC.
+ *     - #PSA_KEY_TYPE_HMAC;
+ *     - #PSA_KEY_TYPE_PASSWORD_HASH.
  *
  * - For ECC keys on a Montgomery elliptic curve
  *   (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a
@@ -3601,6 +3666,10 @@
  * on the derived key based on the attributes and strength of the secret key.
  *
  * \param[in] attributes    The attributes for the new key.
+ *                          If the key type to be created is
+ *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ *                          the policy must be the same as in the current
+ *                          operation.
  * \param[in,out] operation The key derivation operation object to read from.
  * \param[out] key          On success, an identifier for the newly created
  *                          key. For persistent keys, this is the key
@@ -3625,8 +3694,10 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The provided key attributes are not valid for the operation.
  * \retval #PSA_ERROR_NOT_PERMITTED
- *         The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through
- *         a key.
+ *         The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ *         key; or one of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_DERIVE.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be active and completed
  *         all required input steps).
@@ -3648,6 +3719,129 @@
     psa_key_derivation_operation_t *operation,
     mbedtls_svc_key_id_t *key);
 
+/** Compare output data from a key derivation operation to an expected value.
+ *
+ * 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
+ * stream before comparing them.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * This is functionally equivalent to the following code:
+ * \code
+ * psa_key_derivation_output_bytes(operation, tmp, output_length);
+ * if (memcmp(output, tmp, output_length) != 0)
+ *     return PSA_ERROR_INVALID_SIGNATURE;
+ * \endcode
+ * except (1) it works even if the key's policy does not allow outputting the
+ * bytes, and (2) the comparison will be done in constant time.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,
+ * the operation enters an error state and must be aborted by calling
+ * 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 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
+ *         output.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         One of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_VERIFY_DERIVATION.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ *                          The operation's capacity was less than
+ *                          \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.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active and completed
+ *         all required input steps).
+ * \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_key_derivation_verify_bytes(
+    psa_key_derivation_operation_t *operation,
+    const uint8_t *expected_output,
+    size_t output_length);
+
+/** Compare output data from a key derivation operation to an expected value
+ * stored in a key object.
+ *
+ * This function calculates output bytes from a key derivation algorithm and
+ * compares those bytes to an expected value, provided as key of type
+ * #PSA_KEY_TYPE_PASSWORD_HASH.
+ * If you view the key derivation's output as a stream of bytes, this
+ * function destructively reads the number of bytes corresponding the the
+ * length of the expected value from the stream before comparing them.
+ * The operation's capacity decreases by the number of bytes read.
+ *
+ * This is functionally equivalent to exporting the key and calling
+ * psa_key_derivation_verify_bytes() on the result, except that it
+ * works even if the key cannot be exported.
+ *
+ * If this function returns an error status other than
+ * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE,
+ * the operation enters an error state and must be aborted by calling
+ * psa_key_derivation_abort().
+ *
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] expected      A key of type #PSA_KEY_TYPE_PASSWORD_HASH
+ *                          containing the expected output. Its policy must
+ *                          include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag
+ *                          and the permitted algorithm must match the
+ *                          operation. The value of this key was likely
+ *                          computed by a previous call to
+ *                          psa_key_derivation_output_key().
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The output was read successfully, but if differs from the expected
+ *         output.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         The key passed as the expected value does not exist.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key passed as the expected value has an invalid type.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key passed as the expected value does not allow this usage or
+ *         this algorithm; or one of the inputs was a key whose policy didn't
+ *         allow #PSA_KEY_USAGE_VERIFY_DERIVATION.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ *                          The operation's capacity was less than
+ *                          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.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active and completed
+ *         all required input steps).
+ * \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_key_derivation_verify_key(
+    psa_key_derivation_operation_t *operation,
+    psa_key_id_t expected);
+
 /** Abort a key derivation operation.
  *
  * Aborting an operation frees all associated resources except for the \c
diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h
new file mode 100644
index 0000000..1d11b00
--- /dev/null
+++ b/include/psa/crypto_builtin_composites.h
@@ -0,0 +1,92 @@
+/*
+ *  Context structure declaration of the Mbed TLS software-based PSA drivers
+ *  called through the PSA Crypto driver dispatch layer.
+ *  This file contains the context structures of those algorithms which need to
+ *  rely on other algorithms, i.e. are 'composite' algorithms.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * \note This header and its content is not part of the Mbed TLS API and
+ * applications must not depend on it. Its main purpose is to define the
+ * multi-part state objects of the Mbed TLS software-based PSA drivers. The
+ * definition of these objects are then used by crypto_struct.h to define the
+ * implementation-defined types of PSA multi-part state objects.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H
+#define PSA_CRYPTO_BUILTIN_COMPOSITES_H
+
+#include <psa/crypto_driver_common.h>
+
+/*
+ * MAC multi-part operation definitions.
+ */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+#define MBEDTLS_PSA_BUILTIN_MAC
+#endif
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
+typedef struct
+{
+    /** The HMAC algorithm in use */
+    psa_algorithm_t 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];
+} mbedtls_psa_hmac_operation_t;
+
+#define MBEDTLS_PSA_HMAC_OPERATION_INIT {0, PSA_HASH_OPERATION_INIT, {0}}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+
+#include "mbedtls/cmac.h"
+
+typedef struct
+{
+    psa_algorithm_t alg;
+    union
+    {
+        unsigned 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;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
+        mbedtls_cipher_context_t cmac;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+    } ctx;
+} mbedtls_psa_mac_operation_t;
+
+#define MBEDTLS_PSA_MAC_OPERATION_INIT {0, {0}}
+
+/*
+ * BEYOND THIS POINT, TEST DRIVER DECLARATIONS ONLY.
+ */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+typedef mbedtls_psa_mac_operation_t mbedtls_transparent_test_driver_mac_operation_t;
+typedef mbedtls_psa_mac_operation_t mbedtls_opaque_test_driver_mac_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT MBEDTLS_PSA_MAC_OPERATION_INIT
+#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT MBEDTLS_PSA_MAC_OPERATION_INIT
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+#endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */
diff --git a/include/psa/crypto_builtin.h b/include/psa/crypto_builtin_primitives.h
similarity index 93%
rename from include/psa/crypto_builtin.h
rename to include/psa/crypto_builtin_primitives.h
index b3bc140..75801a1 100644
--- a/include/psa/crypto_builtin.h
+++ b/include/psa/crypto_builtin_primitives.h
@@ -1,6 +1,8 @@
 /*
  *  Context structure declaration of the Mbed TLS software-based PSA drivers
  *  called through the PSA Crypto driver dispatch layer.
+ *  This file contains the context structures of those algorithms which do not
+ *  rely on other algorithms, i.e. are 'primitive' algorithms.
  *
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
@@ -28,8 +30,8 @@
  *  limitations under the License.
  */
 
-#ifndef PSA_CRYPTO_BUILTIN_H
-#define PSA_CRYPTO_BUILTIN_H
+#ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H
+#define PSA_CRYPTO_BUILTIN_PRIMITIVES_H
 
 #include <psa/crypto_driver_common.h>
 
@@ -141,4 +143,4 @@
 
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 
-#endif /* PSA_CRYPTO_BUILTIN_H */
+#endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index 736d9ab..eb16492 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -57,6 +57,7 @@
 #define PSA_WANT_ALG_CBC_NO_PADDING             1
 #define PSA_WANT_ALG_CBC_PKCS7                  1
 #define PSA_WANT_ALG_CCM                        1
+#define PSA_WANT_ALG_CMAC                       1
 #define PSA_WANT_ALG_CFB                        1
 #define PSA_WANT_ALG_CHACHA20_POLY1305          1
 #define PSA_WANT_ALG_CMAC                       1
@@ -72,6 +73,9 @@
 #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.
+ * Note: when adding support, also adjust include/mbedtls/config_psa.h */
+//#define PSA_WANT_ALG_PBKDF2_HMAC                1
 #define PSA_WANT_ALG_RIPEMD160                  1
 #define PSA_WANT_ALG_RSA_OAEP                   1
 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
diff --git a/include/psa/crypto_driver_contexts.h b/include/psa/crypto_driver_contexts_composites.h
similarity index 74%
copy from include/psa/crypto_driver_contexts.h
copy to include/psa/crypto_driver_contexts_composites.h
index d725e84..239fdcb 100644
--- a/include/psa/crypto_driver_contexts.h
+++ b/include/psa/crypto_driver_contexts_composites.h
@@ -1,6 +1,8 @@
 /*
  *  Declaration of context structures for use with the PSA driver wrapper
- *  interface.
+ *  interface. This file contains the context structures for 'composite'
+ *  operations, i.e. those operations which need to make use of other operations
+ *  from the primitives (crypto_driver_contexts_primitives.h)
  *
  *  Warning: This file will be auto-generated in the future.
  *
@@ -29,17 +31,16 @@
  *  limitations under the License.
  */
 
-#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_H
-#define PSA_CRYPTO_DRIVER_CONTEXTS_H
+#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H
+#define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H
 
-#include "psa/crypto.h"
 #include "psa/crypto_driver_common.h"
 
 /* Include the context structure definitions for those drivers that were
  * declared during the autogeneration process. */
 
 /* Include the context structure definitions for the Mbed TLS software drivers */
-#include "psa/crypto_builtin.h"
+#include "psa/crypto_builtin_composites.h"
 
 /* Define the context to be used for an operation that is executed through the
  * PSA Driver wrapper layer as the union of all possible driver's contexts.
@@ -50,20 +51,12 @@
 
 typedef union {
     unsigned dummy; /* Make sure this union is always non-empty */
-    mbedtls_psa_hash_operation_t mbedtls_ctx;
+    mbedtls_psa_mac_operation_t mbedtls_ctx;
 #if defined(PSA_CRYPTO_DRIVER_TEST)
-    mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx;
+    mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx;
+    mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx;
 #endif
-} psa_driver_hash_context_t;
+} psa_driver_mac_context_t;
 
-typedef union {
-    unsigned dummy; /* Make sure this union is always non-empty */
-    mbedtls_psa_cipher_operation_t mbedtls_ctx;
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-    mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx;
-    mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx;
-#endif
-} psa_driver_cipher_context_t;
-
-#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_H */
+#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */
 /* End of automatically generated file. */
diff --git a/include/psa/crypto_driver_contexts.h b/include/psa/crypto_driver_contexts_primitives.h
similarity index 88%
rename from include/psa/crypto_driver_contexts.h
rename to include/psa/crypto_driver_contexts_primitives.h
index d725e84..104d4bd 100644
--- a/include/psa/crypto_driver_contexts.h
+++ b/include/psa/crypto_driver_contexts_primitives.h
@@ -1,6 +1,7 @@
 /*
  *  Declaration of context structures for use with the PSA driver wrapper
- *  interface.
+ *  interface. This file contains the context structures for 'primitive'
+ *  operations, i.e. those operations which do not rely on other contexts.
  *
  *  Warning: This file will be auto-generated in the future.
  *
@@ -29,17 +30,16 @@
  *  limitations under the License.
  */
 
-#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_H
-#define PSA_CRYPTO_DRIVER_CONTEXTS_H
+#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H
+#define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H
 
-#include "psa/crypto.h"
 #include "psa/crypto_driver_common.h"
 
 /* Include the context structure definitions for those drivers that were
  * declared during the autogeneration process. */
 
 /* Include the context structure definitions for the Mbed TLS software drivers */
-#include "psa/crypto_builtin.h"
+#include "psa/crypto_builtin_primitives.h"
 
 /* Define the context to be used for an operation that is executed through the
  * PSA Driver wrapper layer as the union of all possible driver's contexts.
@@ -65,5 +65,5 @@
 #endif
 } psa_driver_cipher_context_t;
 
-#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_H */
+#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */
 /* End of automatically generated file. */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 8ac7ce1..47012fd 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -76,8 +76,9 @@
 #include "mbedtls/cmac.h"
 #include "mbedtls/gcm.h"
 
-/* Include the context definition for the compiled-in drivers */
-#include "psa/crypto_driver_contexts.h"
+/* Include the context definition for the compiled-in drivers for the primitive
+ * algorithms. */
+#include "psa/crypto_driver_contexts_primitives.h"
 
 struct psa_hash_operation_s
 {
@@ -98,46 +99,6 @@
     return( v );
 }
 
-#if defined(MBEDTLS_MD_C)
-typedef struct
-{
-        /** The HMAC algorithm in use */
-        psa_algorithm_t 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];
-} psa_hmac_internal_data;
-#endif /* MBEDTLS_MD_C */
-
-struct psa_mac_operation_s
-{
-    psa_algorithm_t alg;
-    unsigned int key_set : 1;
-    unsigned int iv_required : 1;
-    unsigned int iv_set : 1;
-    unsigned int has_input : 1;
-    unsigned int is_sign : 1;
-    uint8_t mac_size;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_MD_C)
-        psa_hmac_internal_data hmac;
-#endif
-#if defined(MBEDTLS_CMAC_C)
-        mbedtls_cipher_context_t cmac;
-#endif
-    } ctx;
-};
-
-#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 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;
-    return( v );
-}
-
 struct psa_cipher_operation_s
 {
     /** Unique ID indicating which driver got assigned to do the
@@ -163,6 +124,31 @@
     return( v );
 }
 
+/* Include the context definition for the compiled-in drivers for the composite
+ * algorithms. */
+#include "psa/crypto_driver_contexts_composites.h"
+
+struct psa_mac_operation_s
+{
+    /** Unique ID indicating which driver got assigned to do the
+     * operation. Since driver contexts are driver-specific, swapping
+     * drivers halfway through the operation is not supported.
+     * 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;
+};
+
+#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;
+    return( v );
+}
+
 struct psa_aead_operation_s
 {
     psa_algorithm_t alg;
@@ -184,12 +170,12 @@
     return( v );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
 typedef struct
 {
     uint8_t *info;
     size_t info_length;
-    psa_hmac_internal_data hmac;
+    psa_mac_operation_t hmac;
     uint8_t prk[PSA_HASH_MAX_SIZE];
     uint8_t output_block[PSA_HASH_MAX_SIZE];
 #if PSA_HASH_MAX_SIZE > 0xff
@@ -200,9 +186,10 @@
     unsigned int state : 2;
     unsigned int info_set : 1;
 } psa_hkdf_key_derivation_t;
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 typedef enum
 {
     PSA_TLS12_PRF_STATE_INIT,       /* no input provided */
@@ -227,17 +214,20 @@
 
     psa_tls12_prf_key_derivation_state_t state;
 
+    uint8_t *secret;
+    size_t secret_length;
     uint8_t *seed;
     size_t seed_length;
     uint8_t *label;
     size_t label_length;
-    psa_hmac_internal_data hmac;
+
     uint8_t 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];
 } psa_tls12_prf_key_derivation_t;
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
 struct psa_key_derivation_s
 {
@@ -248,8 +238,11 @@
     {
         /* Make the union non-empty even with no supported algorithms. */
         uint8_t dummy;
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
         psa_hkdf_key_derivation_t 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;
 #endif
     } ctx;
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 9bfd5ab..bfff968 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -409,11 +409,55 @@
 
 /** A secret for key derivation.
  *
+ * This key type is for high-entropy secrets only. For low-entropy secrets,
+ * #PSA_KEY_TYPE_PASSWORD should be used instead.
+ *
+ * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms.
+ *
  * The key policy determines which key derivation algorithm the key
  * can be used for.
  */
 #define PSA_KEY_TYPE_DERIVE                         ((psa_key_type_t)0x1200)
 
+/** A low-entropy secret for password hashing or key derivation.
+ *
+ * This key type is suitable for passwords and passphrases which are typically
+ * intended to be memorizable by humans, and have a low entropy relative to
+ * their size. It can be used for randomly generated or derived keys with
+ * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable
+ * for such keys. It is not suitable for passwords with extremely low entropy,
+ * such as numerical PINs.
+ *
+ * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of
+ * key derivation algorithms. Algorithms that accept such an input were
+ * designed to accept low-entropy secret and are known as password hashing or
+ * key stretching algorithms.
+ *
+ * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of
+ * key derivation algorithms, as the algorithms that take such an input expect
+ * it to be high-entropy.
+ *
+ * The key policy determines which key derivation algorithm the key can be
+ * used for, among the permissible subset defined above.
+ */
+#define PSA_KEY_TYPE_PASSWORD                       ((psa_key_type_t)0x1203)
+
+/** A secret value that can be used to verify a password hash.
+ *
+ * The key policy determines which key derivation algorithm the key
+ * can be used for, among the same permissible subset as for
+ * #PSA_KEY_TYPE_PASSWORD.
+ */
+#define PSA_KEY_TYPE_PASSWORD_HASH                  ((psa_key_type_t)0x1205)
+
+/** A secret value that can be used in when computing a password hash.
+ *
+ * The key policy determines which key derivation algorithm the key
+ * can be used for, among the subset of algorithms that can use pepper.
+ */
+#define PSA_KEY_TYPE_PEPPER                         ((psa_key_type_t)0x1206)
+
 /** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher.
  *
  * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or
@@ -786,6 +830,24 @@
 #define PSA_ALG_IS_KEY_DERIVATION(alg)                                  \
     (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
 
+/** Whether the specified algorithm is a key stretching / password hashing
+ * algorithm.
+ *
+ * A key stretching / password hashing algorithm is a key derivation algorithm
+ * that is suitable for use with a low-entropy secret such as a password.
+ * Equivalently, it's a key derivation algorithm that uses a
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \p alg is a key stretching / passowrd hashing algorithm, 0
+ *         otherwise. This macro may return either 0 or 1 if \p alg is not a
+ *         supported algorithm identifier.
+ */
+#define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg)                                  \
+    (PSA_ALG_IS_KEY_DERIVATION(alg) &&              \
+     (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)
@@ -1667,6 +1729,67 @@
 #define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg)                         \
     (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))
 
+/* This flag indicates whether the key derivation algorithm is suitable for
+ * use on low-entropy secrets such as password - these algorithms are also
+ * known as key stretching or password hashing schemes. These are also the
+ * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD.
+ *
+ * Those algorithms cannot be combined with a key agreement algorithm.
+ */
+#define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG  ((psa_algorithm_t)0x00800000)
+
+#define PSA_ALG_PBKDF2_HMAC_BASE                ((psa_algorithm_t)0x08800100)
+/** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm.
+ *
+ * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).
+ * This macro specifies the PBKDF2 algorithm constructed using a PRF based on
+ * HMAC with the specified hash.
+ * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA256)` specifies PBKDF2
+ * using the PRF HMAC-SHA-256.
+ *
+ * This key derivation algorithm uses the following inputs, which must be
+ * provided in the following order:
+ * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count.
+ *   This input step must be used exactly once.
+ * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt.
+ *   This input step must be used one or more times; if used several times, the
+ *   inputs will be concatenated. This can be used to build the final salt
+ *   from multiple sources, both public and secret (also known as pepper).
+ * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed.
+ *   This input step must be used exactly once.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *
+ * \return              The corresponding PBKDF2-HMAC-XXX algorithm.
+ * \return              Unspecified if \p hash_alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_PBKDF2_HMAC(hash_alg)                                  \
+    (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+
+/** Whether the specified algorithm is a PBKDF2-HMAC algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise.
+ *         This macro may return either 0 or 1 if \c alg is not a supported
+ *         key derivation algorithm identifier.
+ */
+#define PSA_ALG_IS_PBKDF2_HMAC(alg)                                    \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE)
+
+/** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm.
+ *
+ * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).
+ * This macro specifies the PBKDF2 algorithm constructed using the
+ * AES-CMAC-PRF-128 PRF specified by RFC 4615.
+ *
+ * This key derivation algorithm uses the same inputs as
+ * #PSA_ALG_PBKDF2_HMAC() with the same constraints.
+ */
+#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128         ((psa_algorithm_t)0x08800200)
+
 #define PSA_ALG_KEY_DERIVATION_MASK             ((psa_algorithm_t)0xfe00ffff)
 #define PSA_ALG_KEY_AGREEMENT_MASK              ((psa_algorithm_t)0xffff0000)
 
@@ -1804,6 +1927,18 @@
      (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 :  \
      (alg) == PSA_ALG_ANY_HASH)
 
+/** Get the hash used by a composite algorithm.
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return The underlying hash algorithm if alg is a composite algorithm that
+ * uses a hash algorithm.
+ *
+ * \return \c 0 if alg is not a composite algorithm that uses a hash.
+ */
+#define PSA_ALG_GET_HASH(alg) \
+        (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t)0) : 0x02000000 | ((alg) & 0x000000ff))
+
 /**@}*/
 
 /** \defgroup key_lifetimes Key lifetimes
@@ -2083,10 +2218,34 @@
  */
 #define PSA_KEY_USAGE_VERIFY_HASH               ((psa_key_usage_t)0x00002000)
 
-/** Whether the key may be used to derive other keys.
+/** 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.
  */
 #define PSA_KEY_USAGE_DERIVE                    ((psa_key_usage_t)0x00004000)
 
+/** Whether the key may be used to verify the result of a key derivation,
+ * including password hashing.
+ *
+ * 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).
+ */
+#define PSA_KEY_USAGE_VERIFY_DERIVATION         ((psa_key_usage_t)0x00008000)
+
 /**@}*/
 
 /** \defgroup derivation Key derivation
@@ -2102,11 +2261,32 @@
  *
  * 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 keys: the operation will only allow
- * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key().
+ * 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().
  */
 #define PSA_KEY_DERIVATION_INPUT_SECRET     ((psa_key_derivation_step_t)0x0101)
 
+/** A low-entropy secret input for password hashing / key stretching.
+ *
+ * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to
+ * psa_key_derivation_input_key()) or a direct input (passed to
+ * psa_key_derivation_input_bytes()) that is a password or passphrase. It can
+ * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or
+ * the shared secret resulting from a key agreement.
+ *
+ * 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().
+ */
+#define PSA_KEY_DERIVATION_INPUT_PASSWORD   ((psa_key_derivation_step_t)0x0102)
+
 /** A label for key derivation.
  *
  * This should be a direct input.
@@ -2117,7 +2297,8 @@
 /** A salt for key derivation.
  *
  * This should be a direct input.
- * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA.
+ * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or
+ * #PSA_KEY_TYPE_PEPPER.
  */
 #define PSA_KEY_DERIVATION_INPUT_SALT       ((psa_key_derivation_step_t)0x0202)
 
@@ -2135,6 +2316,12 @@
  */
 #define PSA_KEY_DERIVATION_INPUT_SEED       ((psa_key_derivation_step_t)0x0204)
 
+/** A cost parameter for password hashing / key stretching.
+ *
+ * This must be a direct input, passed to psa_key_derivation_input_integer().
+ */
+#define PSA_KEY_DERIVATION_INPUT_COST       ((psa_key_derivation_step_t)0x0205)
+
 /**@}*/
 
 /** \defgroup helper_macros Helper macros
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index e7ba130..f31820a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -68,6 +68,7 @@
     psa_crypto_driver_wrappers.c
     psa_crypto_ecp.c
     psa_crypto_hash.c
+    psa_crypto_mac.c
     psa_crypto_rsa.c
     psa_crypto_se.c
     psa_crypto_slot_management.c
diff --git a/library/Makefile b/library/Makefile
index 17e42c2..d7fa4d9 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -125,6 +125,7 @@
 	     psa_crypto_driver_wrappers.o \
 	     psa_crypto_ecp.o \
 	     psa_crypto_hash.o \
+	     psa_crypto_mac.o \
 	     psa_crypto_rsa.o \
 	     psa_crypto_se.o \
 	     psa_crypto_slot_management.o \
diff --git a/library/net_sockets.c b/library/net_sockets.c
index ad1ac13..8f79b74 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -20,8 +20,12 @@
 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
  * be set before config.h, which pulls in glibc's features.h indirectly.
  * Harmless on other platforms. */
+#ifndef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 200112L
+#endif
+#ifndef _XOPEN_SOURCE
 #define _XOPEN_SOURCE 600 /* sockaddr_storage */
+#endif
 
 #include "common.h"
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index c153217..2583735 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -35,6 +35,7 @@
 #include "psa_crypto_driver_wrappers.h"
 #include "psa_crypto_ecp.h"
 #include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
 #include "psa_crypto_rsa.h"
 #include "psa_crypto_ecp.h"
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -92,20 +93,6 @@
 
 #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
 
-/* constant-time buffer comparison */
-static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
-{
-    size_t i;
-    unsigned char diff = 0;
-
-    for( i = 0; i < n; i++ )
-        diff |= a[i] ^ b[i];
-
-    return( diff );
-}
-
-
-
 /****************************************************************/
 /* Global data, support functions and library management */
 /****************************************************************/
@@ -1507,6 +1494,7 @@
                              PSA_KEY_USAGE_DECRYPT |
                              PSA_KEY_USAGE_SIGN_HASH |
                              PSA_KEY_USAGE_VERIFY_HASH |
+                             PSA_KEY_USAGE_VERIFY_DERIVATION |
                              PSA_KEY_USAGE_DERIVE ) ) != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
@@ -2183,7 +2171,7 @@
         return( status );
     if( actual_hash_length != hash_length )
         return( PSA_ERROR_INVALID_SIGNATURE );
-    if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
+    if( mbedtls_psa_safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
         return( PSA_ERROR_INVALID_SIGNATURE );
     return( PSA_SUCCESS );
 }
@@ -2219,7 +2207,7 @@
         return( status );
     if( actual_hash_length != hash_length )
         return( PSA_ERROR_INVALID_SIGNATURE );
-    if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
+    if( mbedtls_psa_safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
         return( PSA_ERROR_INVALID_SIGNATURE );
     return( PSA_SUCCESS );
 }
@@ -2246,222 +2234,19 @@
 /* MAC */
 /****************************************************************/
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static size_t psa_get_hash_block_size( psa_algorithm_t alg )
-{
-    switch( alg )
-    {
-        case PSA_ALG_MD2:
-            return( 16 );
-        case PSA_ALG_MD4:
-            return( 64 );
-        case PSA_ALG_MD5:
-            return( 64 );
-        case PSA_ALG_RIPEMD160:
-            return( 64 );
-        case PSA_ALG_SHA_1:
-            return( 64 );
-        case PSA_ALG_SHA_224:
-            return( 64 );
-        case PSA_ALG_SHA_256:
-            return( 64 );
-        case PSA_ALG_SHA_384:
-            return( 128 );
-        case PSA_ALG_SHA_512:
-            return( 128 );
-        default:
-            return( 0 );
-    }
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) */
-
-/* Initialize the MAC operation structure. Once this function has been
- * called, psa_mac_abort can run and will do the right thing. */
-static psa_status_t psa_mac_init( psa_mac_operation_t *operation,
-                                  psa_algorithm_t alg )
-{
-    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
-
-    operation->alg = PSA_ALG_FULL_LENGTH_MAC( alg );
-    operation->key_set = 0;
-    operation->iv_set = 0;
-    operation->iv_required = 0;
-    operation->has_input = 0;
-    operation->is_sign = 0;
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        operation->iv_required = 0;
-        mbedtls_cipher_init( &operation->ctx.cmac );
-        status = PSA_SUCCESS;
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        /* We'll set up the hash operation later in psa_hmac_setup_internal. */
-        operation->ctx.hmac.alg = 0;
-        status = PSA_SUCCESS;
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        if( ! PSA_ALG_IS_MAC( alg ) )
-            status = PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    if( status != PSA_SUCCESS )
-        memset( operation, 0, sizeof( *operation ) );
-    return( status );
-}
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
-{
-    mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) );
-    return( psa_hash_abort( &hmac->hash_ctx ) );
-}
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-
 psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
 {
-    if( operation->alg == 0 )
-    {
-        /* The object has (apparently) been initialized but it is not
-         * in use. It's ok to call abort on such an object, and there's
-         * nothing to do. */
+    /* Aborting a non-active operation is allowed */
+    if( operation->id == 0 )
         return( PSA_SUCCESS );
-    }
-    else
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        mbedtls_cipher_free( &operation->ctx.cmac );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        psa_hmac_abort_internal( &operation->ctx.hmac );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        /* Sanity check (shouldn't happen: operation->alg should
-         * always have been initialized to a valid value). */
-        goto bad_state;
-    }
 
-    operation->alg = 0;
-    operation->key_set = 0;
-    operation->iv_set = 0;
-    operation->iv_required = 0;
-    operation->has_input = 0;
+    psa_status_t status = psa_driver_wrapper_mac_abort( operation );
+    operation->mac_size = 0;
     operation->is_sign = 0;
-
-    return( PSA_SUCCESS );
-
-bad_state:
-    /* If abort is called on an uninitialized object, we can't trust
-     * anything. Wipe the object in case it contains confidential data.
-     * This may result in a memory leak if a pointer gets overwritten,
-     * but it's too late to do anything about this. */
-    memset( operation, 0, sizeof( *operation ) );
-    return( PSA_ERROR_BAD_STATE );
-}
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-static psa_status_t psa_cmac_setup( psa_mac_operation_t *operation,
-                                    psa_key_slot_t *slot )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_cipher_info_t *cipher_info =
-            mbedtls_cipher_info_from_psa( PSA_ALG_CMAC,
-                                          slot->attr.type, slot->attr.bits,
-                                          NULL );
-    if( cipher_info == NULL )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-    ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
-    if( ret != 0 )
-        goto exit;
-
-    ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
-                                      slot->key.data,
-                                      slot->attr.bits );
-exit:
-    return( mbedtls_to_psa_error( ret ) );
-}
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac,
-                                             const uint8_t *key,
-                                             size_t key_length,
-                                             psa_algorithm_t hash_alg )
-{
-    uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
-    size_t i;
-    size_t hash_size = PSA_HASH_LENGTH( hash_alg );
-    size_t block_size = psa_get_hash_block_size( hash_alg );
-    psa_status_t status;
-
-    hmac->alg = hash_alg;
-
-    /* Sanity checks on block_size, to guarantee that there won't be a buffer
-     * overflow below. This should never trigger if the hash algorithm
-     * is implemented correctly. */
-    /* The size checks against the ipad and opad buffers cannot be written
-     * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
-     * because that triggers -Wlogical-op on GCC 7.3. */
-    if( block_size > sizeof( ipad ) )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    if( block_size > sizeof( hmac->opad ) )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    if( block_size < hash_size )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-    if( key_length > block_size )
-    {
-        status = psa_hash_compute( hash_alg, key, key_length,
-                                   ipad, sizeof( ipad ), &key_length );
-        if( status != PSA_SUCCESS )
-            goto cleanup;
-    }
-    /* A 0-length key is not commonly used in HMAC when used as a MAC,
-     * but it is permitted. It is common when HMAC is used in HKDF, for
-     * example. Don't call `memcpy` in the 0-length because `key` could be
-     * an invalid pointer which would make the behavior undefined. */
-    else if( key_length != 0 )
-        memcpy( ipad, key, key_length );
-
-    /* ipad contains the key followed by garbage. Xor and fill with 0x36
-     * to create the ipad value. */
-    for( i = 0; i < key_length; i++ )
-        ipad[i] ^= 0x36;
-    memset( ipad + key_length, 0x36, block_size - key_length );
-
-    /* Copy the key material from ipad to opad, flipping the requisite bits,
-     * and filling the rest of opad with the requisite constant. */
-    for( i = 0; i < key_length; i++ )
-        hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
-    memset( hmac->opad + key_length, 0x5C, block_size - key_length );
-
-    status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
-    if( status != PSA_SUCCESS )
-        goto cleanup;
-
-    status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
-
-cleanup:
-    mbedtls_platform_zeroize( ipad, sizeof( ipad ) );
+    operation->id = 0;
 
     return( status );
 }
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 
 static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
                                    mbedtls_svc_key_id_t key,
@@ -2471,35 +2256,38 @@
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_key_usage_t usage =
-        is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH;
 
     /* A context must be freshly initialized before it can be set up. */
-    if( operation->alg != 0 )
-    {
+    if( operation->id != 0 )
         return( PSA_ERROR_BAD_STATE );
-    }
 
-    status = psa_mac_init( operation, alg );
+    if( ! PSA_ALG_IS_MAC( alg ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    status = psa_get_and_lock_key_slot_with_policy(
+                 key,
+                 &slot,
+                 is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH,
+                 alg );
     if( status != PSA_SUCCESS )
         return( status );
-    if( is_sign )
-        operation->is_sign = 1;
 
-    status = psa_get_and_lock_transparent_key_slot_with_policy(
-                 key, &slot, usage, alg );
-    if( status != PSA_SUCCESS )
-        goto exit;
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
 
     /* Validate the combination of key type and algorithm */
-    status = psa_mac_key_can_do( alg, slot->attr.type );
+    status = psa_mac_key_can_do( alg, psa_get_key_type( &attributes ) );
     if( status != PSA_SUCCESS )
         goto exit;
 
-    /* Get the output length for the algorithm and key combination. None of the
-     * currently supported algorithms have an output length dependent on actual
-     * key size, so setting it to a bogus value is currently OK. */
-    operation->mac_size = PSA_MAC_LENGTH( slot->attr.type, 0, alg );
+    operation->is_sign = is_sign;
+
+    /* Get the output length for the algorithm and key combination */
+    operation->mac_size = PSA_MAC_LENGTH(
+                            psa_get_key_type( &attributes ),
+                            psa_get_key_bits( &attributes ),
+                            alg );
 
     if( operation->mac_size < 4 )
     {
@@ -2511,8 +2299,9 @@
         goto exit;
     }
 
-    if( operation->mac_size >
-        PSA_MAC_LENGTH( slot->attr.type, 0, PSA_ALG_FULL_LENGTH_MAC( alg ) ) )
+    if( operation->mac_size > PSA_MAC_LENGTH( psa_get_key_type( &attributes ),
+                                              psa_get_key_bits( &attributes ),
+                                              PSA_ALG_FULL_LENGTH_MAC( alg ) ) )
     {
         /* It's impossible to "truncate" to a larger length than the full length
          * of the algorithm. */
@@ -2520,49 +2309,27 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-    if( PSA_ALG_FULL_LENGTH_MAC( alg ) == PSA_ALG_CMAC )
+    /* Dispatch the MAC setup call with validated input */
+    if( is_sign )
     {
-        status = psa_cmac_setup( operation, slot );
+        status = psa_driver_wrapper_mac_sign_setup( operation,
+                                                    &attributes,
+                                                    slot->key.data,
+                                                    slot->key.bytes,
+                                                    alg );
     }
     else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( alg ) )
     {
-        /* Sanity check. This shouldn't fail on a valid configuration. */
-        if( operation->mac_size > sizeof( operation->ctx.hmac.opad ) )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-
-        if( slot->attr.type != PSA_KEY_TYPE_HMAC )
-        {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-            goto exit;
-        }
-
-        status = psa_hmac_setup_internal( &operation->ctx.hmac,
-                                          slot->key.data,
-                                          slot->key.bytes,
-                                          PSA_ALG_HMAC_GET_HASH( alg ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
+        status = psa_driver_wrapper_mac_verify_setup( operation,
+                                                      &attributes,
+                                                      slot->key.data,
+                                                      slot->key.bytes,
+                                                      alg );
     }
 
 exit:
     if( status != PSA_SUCCESS )
-    {
         psa_mac_abort( operation );
-    }
-    else
-    {
-        operation->key_set = 1;
-    }
 
     unlock_status = psa_unlock_key_slot( slot );
 
@@ -2587,200 +2354,102 @@
                              const uint8_t *input,
                              size_t input_length )
 {
-    psa_status_t status = PSA_ERROR_BAD_STATE;
-    if( ! operation->key_set )
+    if( operation->id == 0 )
         return( PSA_ERROR_BAD_STATE );
-    if( operation->iv_required && ! operation->iv_set )
-        return( PSA_ERROR_BAD_STATE );
-    operation->has_input = 1;
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        int ret = mbedtls_cipher_cmac_update( &operation->ctx.cmac,
-                                              input, input_length );
-        status = mbedtls_to_psa_error( ret );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input,
-                                  input_length );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        /* This shouldn't happen if `operation` was initialized by
-         * a setup function. */
-        return( PSA_ERROR_BAD_STATE );
-    }
+    /* Don't require hash implementations to behave correctly on a
+     * zero-length input, which may have an invalid pointer. */
+    if( input_length == 0 )
+        return( PSA_SUCCESS );
 
+    psa_status_t status = psa_driver_wrapper_mac_update( operation,
+                                                         input, input_length );
     if( status != PSA_SUCCESS )
         psa_mac_abort( operation );
+
     return( status );
 }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac,
-                                              uint8_t *mac,
-                                              size_t mac_size )
-{
-    uint8_t tmp[MBEDTLS_MD_MAX_SIZE];
-    psa_algorithm_t hash_alg = hmac->alg;
-    size_t hash_size = 0;
-    size_t block_size = psa_get_hash_block_size( hash_alg );
-    psa_status_t status;
-
-    status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
-    if( status != PSA_SUCCESS )
-        return( status );
-    /* From here on, tmp needs to be wiped. */
-
-    status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    memcpy( mac, tmp, mac_size );
-
-exit:
-    mbedtls_platform_zeroize( tmp, hash_size );
-    return( status );
-}
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-
-static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
-                                             uint8_t *mac,
-                                             size_t mac_size )
-{
-    if( ! operation->key_set )
-        return( PSA_ERROR_BAD_STATE );
-    if( operation->iv_required && ! operation->iv_set )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( mac_size < operation->mac_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
-        int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp );
-        if( ret == 0 )
-            memcpy( mac, tmp, operation->mac_size );
-        mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-        return( mbedtls_to_psa_error( ret ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        return( psa_hmac_finish_internal( &operation->ctx.hmac,
-                                          mac, operation->mac_size ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        /* This shouldn't happen if `operation` was initialized by
-         * a setup function. */
-        return( PSA_ERROR_BAD_STATE );
-    }
-}
-
 psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation,
                                   uint8_t *mac,
                                   size_t mac_size,
                                   size_t *mac_length )
 {
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( operation->alg == 0 )
-    {
-        return( PSA_ERROR_BAD_STATE );
-    }
-
-    /* Fill the output buffer with something that isn't a valid mac
-     * (barring an attack on the mac and deliberately-crafted input),
-     * in case the caller doesn't check the return status properly. */
+    /* Set the output length and content to a safe default, such that in
+     * case the caller misses an error check, the output would be an
+     * unachievable MAC. */
     *mac_length = mac_size;
-    /* If mac_size is 0 then mac may be NULL and then the
-     * call to memset would have undefined behavior. */
-    if( mac_size != 0 )
-        memset( mac, '!', mac_size );
+
+    if( operation->id == 0 )
+        return( PSA_ERROR_BAD_STATE );
 
     if( ! operation->is_sign )
-    {
         return( PSA_ERROR_BAD_STATE );
-    }
 
-    status = psa_mac_finish_internal( operation, mac, mac_size );
+    /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL)
+     * once all the error checks are done. */
+    if( operation->mac_size == 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( mac_size < operation->mac_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+    status = psa_driver_wrapper_mac_sign_finish( operation,
+                                                 mac, operation->mac_size,
+                                                 mac_length );
 
     if( status == PSA_SUCCESS )
     {
-        status = psa_mac_abort( operation );
-        if( status == PSA_SUCCESS )
-            *mac_length = operation->mac_size;
-        else
-            memset( mac, '!', mac_size );
+        /* Set the excess room in the output buffer to an invalid value, to
+         * avoid potentially leaking a longer MAC. */
+        if( mac_size > operation->mac_size )
+            memset( &mac[operation->mac_size],
+                    '!',
+                    mac_size - operation->mac_size );
     }
     else
-        psa_mac_abort( operation );
-    return( status );
+    {
+        /* Set the output length and content to a safe default, such that in
+         * case the caller misses an error check, the output would be an
+         * unachievable MAC. */
+        *mac_length = mac_size;
+        memset( mac, '!', mac_size );
+    }
+
+    abort_status = psa_mac_abort( operation );
+
+    return( status == PSA_SUCCESS ? abort_status : status );
 }
 
 psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation,
                                     const uint8_t *mac,
                                     size_t mac_length )
 {
-    uint8_t actual_mac[PSA_MAC_MAX_SIZE];
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( operation->alg == 0 )
-    {
+    if( operation->id == 0 )
         return( PSA_ERROR_BAD_STATE );
-    }
 
     if( operation->is_sign )
-    {
         return( PSA_ERROR_BAD_STATE );
-    }
+
     if( operation->mac_size != mac_length )
     {
         status = PSA_ERROR_INVALID_SIGNATURE;
         goto cleanup;
     }
 
-    status = psa_mac_finish_internal( operation,
-                                      actual_mac, sizeof( actual_mac ) );
-    if( status != PSA_SUCCESS )
-        goto cleanup;
-
-    if( safer_memcmp( mac, actual_mac, mac_length ) != 0 )
-        status = PSA_ERROR_INVALID_SIGNATURE;
+    status = psa_driver_wrapper_mac_verify_finish( operation,
+                                                   mac, mac_length );
 
 cleanup:
-    if( status == PSA_SUCCESS )
-        status = psa_mac_abort( operation );
-    else
-        psa_mac_abort( operation );
+    abort_status = psa_mac_abort( operation );
 
-    mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
-
-    return( status );
+    return( status == PSA_SUCCESS ? abort_status : status );
 }
 
 
@@ -3553,7 +3222,35 @@
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 #define AT_LEAST_ONE_BUILTIN_KDF
-#endif
+#endif /* At least one builtin KDF */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_key_derivation_start_hmac(
+    psa_mac_operation_t *operation,
+    psa_algorithm_t hash_alg,
+    const uint8_t *hmac_key,
+    size_t hmac_key_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
+    psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( hmac_key_length ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+
+    operation->is_sign = 1;
+    operation->mac_size = PSA_HASH_LENGTH( hash_alg );
+
+    status = psa_driver_wrapper_mac_sign_setup( operation,
+                                                &attributes,
+                                                hmac_key, hmac_key_length,
+                                                PSA_ALG_HMAC( hash_alg ) );
+
+    psa_reset_key_attributes( &attributes );
+    return( status );
+}
+#endif /* KDF algorithms reliant on HMAC */
 
 #define HKDF_STATE_INIT 0 /* no input yet */
 #define HKDF_STATE_STARTED 1 /* got salt */
@@ -3584,7 +3281,7 @@
     if( PSA_ALG_IS_HKDF( kdf_alg ) )
     {
         mbedtls_free( operation->ctx.hkdf.info );
-        status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac );
+        status = psa_mac_abort( &operation->ctx.hkdf.hmac );
     }
     else
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF */
@@ -3594,6 +3291,13 @@
              /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */
              PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
+        if( operation->ctx.tls12_prf.secret != NULL )
+        {
+            mbedtls_platform_zeroize( operation->ctx.tls12_prf.secret,
+                                      operation->ctx.tls12_prf.secret_length );
+            mbedtls_free( operation->ctx.tls12_prf.secret );
+        }
+
         if( operation->ctx.tls12_prf.seed != NULL )
         {
             mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed,
@@ -3608,7 +3312,7 @@
             mbedtls_free( operation->ctx.tls12_prf.label );
         }
 
-        status = psa_hmac_abort_internal( &operation->ctx.tls12_prf.hmac );
+        status = PSA_SUCCESS;
 
         /* We leave the fields Ai and output_block to be erased safely by the
          * mbedtls_platform_zeroize() in the end of this function. */
@@ -3651,11 +3355,12 @@
 /* Read some bytes from an HKDF-based operation. This performs a chunk
  * of the expand phase of the HKDF algorithm. */
 static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf,
-                                             psa_algorithm_t hash_alg,
-                                             uint8_t *output,
-                                             size_t output_length )
+                                                  psa_algorithm_t hash_alg,
+                                                  uint8_t *output,
+                                                  size_t output_length )
 {
     uint8_t hash_length = PSA_HASH_LENGTH( hash_alg );
+    size_t hmac_output_length;
     psa_status_t status;
 
     if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set )
@@ -3685,31 +3390,35 @@
         /* We need a new block */
         ++hkdf->block_number;
         hkdf->offset_in_block = 0;
-        status = psa_hmac_setup_internal( &hkdf->hmac,
-                                          hkdf->prk, hash_length,
-                                          hash_alg );
+
+        status = psa_key_derivation_start_hmac( &hkdf->hmac,
+                                                hash_alg,
+                                                hkdf->prk,
+                                                hash_length );
         if( status != PSA_SUCCESS )
             return( status );
+
         if( hkdf->block_number != 1 )
         {
-            status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                      hkdf->output_block,
-                                      hash_length );
+            status = psa_mac_update( &hkdf->hmac,
+                                     hkdf->output_block,
+                                     hash_length );
             if( status != PSA_SUCCESS )
                 return( status );
         }
-        status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                  hkdf->info,
-                                  hkdf->info_length );
+        status = psa_mac_update( &hkdf->hmac,
+                                 hkdf->info,
+                                 hkdf->info_length );
         if( status != PSA_SUCCESS )
             return( status );
-        status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                  &hkdf->block_number, 1 );
+        status = psa_mac_update( &hkdf->hmac,
+                                 &hkdf->block_number, 1 );
         if( status != PSA_SUCCESS )
             return( status );
-        status = psa_hmac_finish_internal( &hkdf->hmac,
-                                           hkdf->output_block,
-                                           sizeof( hkdf->output_block ) );
+        status = psa_mac_sign_finish( &hkdf->hmac,
+                                      hkdf->output_block,
+                                      sizeof( hkdf->output_block ),
+                                      &hmac_output_length );
         if( status != PSA_SUCCESS )
             return( status );
     }
@@ -3726,7 +3435,8 @@
 {
     psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg );
     uint8_t hash_length = PSA_HASH_LENGTH( hash_alg );
-    psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT;
+    psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT;
+    size_t hmac_output_length;
     psa_status_t status, cleanup_status;
 
     /* We can't be wanting more output after block 0xff, otherwise
@@ -3758,10 +3468,10 @@
      * `block_number`.
      */
 
-    /* Save the hash context before using it, to preserve the hash state with
-     * only the inner padding in it. We need this, because inner padding depends
-     * on the key (secret in the RFC's terminology). */
-    status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup );
+    status = psa_key_derivation_start_hmac( &hmac,
+                                            hash_alg,
+                                            tls12_prf->secret,
+                                            tls12_prf->secret_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
 
@@ -3771,57 +3481,58 @@
         /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads
          * the variable seed and in this instance means it in the context of the
          * P_hash function, where seed = label + seed.) */
-        status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->label, tls12_prf->label_length );
+        status = psa_mac_update( &hmac,
+                                 tls12_prf->label,
+                                 tls12_prf->label_length );
         if( status != PSA_SUCCESS )
             goto cleanup;
-        status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->seed, tls12_prf->seed_length );
+        status = psa_mac_update( &hmac,
+                                 tls12_prf->seed,
+                                 tls12_prf->seed_length );
         if( status != PSA_SUCCESS )
             goto cleanup;
     }
     else
     {
         /* A(i) = HMAC_hash(secret, A(i-1)) */
-        status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->Ai, hash_length );
+        status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length );
         if( status != PSA_SUCCESS )
             goto cleanup;
     }
 
-    status = psa_hmac_finish_internal( &tls12_prf->hmac,
-                                       tls12_prf->Ai, hash_length );
-    if( status != PSA_SUCCESS )
-        goto cleanup;
-    status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx );
+    status = psa_mac_sign_finish( &hmac,
+                                  tls12_prf->Ai, hash_length,
+                                  &hmac_output_length );
+    if( hmac_output_length != hash_length )
+        status = PSA_ERROR_CORRUPTION_DETECTED;
     if( status != PSA_SUCCESS )
         goto cleanup;
 
     /* Calculate HMAC_hash(secret, A(i) + label + seed). */
-    status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->Ai, hash_length );
+    status = psa_key_derivation_start_hmac( &hmac,
+                                            hash_alg,
+                                            tls12_prf->secret,
+                                            tls12_prf->secret_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->label, tls12_prf->label_length );
+    status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->seed, tls12_prf->seed_length );
+    status = psa_mac_update( &hmac, tls12_prf->label, tls12_prf->label_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hmac_finish_internal( &tls12_prf->hmac,
-                                       tls12_prf->output_block, hash_length );
+    status = psa_mac_update( &hmac, tls12_prf->seed, tls12_prf->seed_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx );
+    status = psa_mac_sign_finish( &hmac,
+                                  tls12_prf->output_block, hash_length,
+                                  &hmac_output_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
 
 
 cleanup:
-
-    cleanup_status = psa_hash_abort( &backup );
+    cleanup_status = psa_mac_abort( &hmac );
     if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS )
         status = cleanup_status;
 
@@ -3918,8 +3629,8 @@
         PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
         status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf,
-                                               kdf_alg, output,
-                                               output_length );
+                                                    kdf_alg, output,
+                                                    output_length );
     }
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
@@ -4147,33 +3858,37 @@
         case PSA_KEY_DERIVATION_INPUT_SALT:
             if( hkdf->state != HKDF_STATE_INIT )
                 return( PSA_ERROR_BAD_STATE );
-            status = psa_hmac_setup_internal( &hkdf->hmac,
-                                              data, data_length,
-                                              hash_alg );
-            if( status != PSA_SUCCESS )
-                return( status );
-            hkdf->state = HKDF_STATE_STARTED;
-            return( PSA_SUCCESS );
+            else
+            {
+                status = psa_key_derivation_start_hmac( &hkdf->hmac,
+                                                        hash_alg,
+                                                        data, data_length );
+                if( status != PSA_SUCCESS )
+                    return( status );
+                hkdf->state = HKDF_STATE_STARTED;
+                return( PSA_SUCCESS );
+            }
         case PSA_KEY_DERIVATION_INPUT_SECRET:
             /* If no salt was provided, use an empty salt. */
             if( hkdf->state == HKDF_STATE_INIT )
             {
-                status = psa_hmac_setup_internal( &hkdf->hmac,
-                                                  NULL, 0,
-                                                  hash_alg );
+                status = psa_key_derivation_start_hmac( &hkdf->hmac,
+                                                        hash_alg,
+                                                        NULL, 0 );
                 if( status != PSA_SUCCESS )
                     return( status );
                 hkdf->state = HKDF_STATE_STARTED;
             }
             if( hkdf->state != HKDF_STATE_STARTED )
                 return( PSA_ERROR_BAD_STATE );
-            status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                      data, data_length );
+            status = psa_mac_update( &hkdf->hmac,
+                                     data, data_length );
             if( status != PSA_SUCCESS )
                 return( status );
-            status = psa_hmac_finish_internal( &hkdf->hmac,
-                                               hkdf->prk,
-                                               sizeof( hkdf->prk ) );
+            status = psa_mac_sign_finish( &hkdf->hmac,
+                                          hkdf->prk,
+                                          sizeof( hkdf->prk ),
+                                          &data_length );
             if( status != PSA_SUCCESS )
                 return( status );
             hkdf->offset_in_block = PSA_HASH_LENGTH( hash_alg );
@@ -4226,17 +3941,21 @@
 }
 
 static psa_status_t psa_tls12_prf_set_key( psa_tls12_prf_key_derivation_t *prf,
-                                           psa_algorithm_t hash_alg,
                                            const uint8_t *data,
                                            size_t data_length )
 {
-    psa_status_t status;
     if( prf->state != PSA_TLS12_PRF_STATE_SEED_SET )
         return( PSA_ERROR_BAD_STATE );
 
-    status = psa_hmac_setup_internal( &prf->hmac, data, data_length, hash_alg );
-    if( status != PSA_SUCCESS )
-        return( status );
+    if( data_length != 0 )
+    {
+        prf->secret = mbedtls_calloc( 1, data_length );
+        if( prf->secret == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+        memcpy( prf->secret, data, data_length );
+        prf->secret_length = data_length;
+    }
 
     prf->state = PSA_TLS12_PRF_STATE_KEY_SET;
 
@@ -4266,7 +3985,6 @@
 }
 
 static psa_status_t psa_tls12_prf_input( psa_tls12_prf_key_derivation_t *prf,
-                                         psa_algorithm_t hash_alg,
                                          psa_key_derivation_step_t step,
                                          const uint8_t *data,
                                          size_t data_length )
@@ -4276,7 +3994,7 @@
         case PSA_KEY_DERIVATION_INPUT_SEED:
             return( psa_tls12_prf_set_seed( prf, data, data_length ) );
         case PSA_KEY_DERIVATION_INPUT_SECRET:
-            return( psa_tls12_prf_set_key( prf, hash_alg, data, data_length ) );
+            return( psa_tls12_prf_set_key( prf, data, data_length ) );
         case PSA_KEY_DERIVATION_INPUT_LABEL:
             return( psa_tls12_prf_set_label( prf, data, data_length ) );
         default:
@@ -4289,7 +4007,6 @@
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 static psa_status_t psa_tls12_prf_psk_to_ms_set_key(
     psa_tls12_prf_key_derivation_t *prf,
-    psa_algorithm_t hash_alg,
     const uint8_t *data,
     size_t data_length )
 {
@@ -4316,7 +4033,7 @@
     memcpy( cur, data, data_length );
     cur += data_length;
 
-    status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms );
+    status = psa_tls12_prf_set_key( prf, pms, cur - pms );
 
     mbedtls_platform_zeroize( pms, sizeof( pms ) );
     return( status );
@@ -4324,18 +4041,17 @@
 
 static psa_status_t psa_tls12_prf_psk_to_ms_input(
     psa_tls12_prf_key_derivation_t *prf,
-    psa_algorithm_t hash_alg,
     psa_key_derivation_step_t step,
     const uint8_t *data,
     size_t data_length )
 {
     if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
     {
-        return( psa_tls12_prf_psk_to_ms_set_key( prf, hash_alg,
+        return( psa_tls12_prf_psk_to_ms_set_key( prf,
                                                  data, data_length ) );
     }
 
-    return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) );
+    return( psa_tls12_prf_input( prf, step, data, data_length ) );
 }
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
@@ -4400,7 +4116,6 @@
     if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) )
     {
         status = psa_tls12_prf_input( &operation->ctx.tls12_prf,
-                                      PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                       step, data, data_length );
     }
     else
@@ -4409,7 +4124,6 @@
     if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
         status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf,
-                                                PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                                 step, data, data_length );
     }
     else
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 90f9d18..b75e59a 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -30,6 +30,26 @@
 #include "psa/crypto.h"
 #include "psa/crypto_se_driver.h"
 
+/** Constant-time buffer comparison
+ *
+ * \param[in]  a    Left-hand buffer for comparison.
+ * \param[in]  b    Right-hand buffer for comparison.
+ * \param n         Amount of bytes to compare.
+ *
+ * \return 0 if the buffer contents are equal, non-zero otherwise
+ */
+static inline int mbedtls_psa_safer_memcmp(
+    const uint8_t *a, const uint8_t *b, size_t n )
+{
+    size_t i;
+    unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+        diff |= a[i] ^ b[i];
+
+    return( diff );
+}
+
 /** The data structure representing a key slot, containing key material
  * and metadata for one key.
  */
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
index 9bef02c..795e424 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -24,6 +24,7 @@
 #include "psa_crypto_core.h"
 #include "psa_crypto_driver_wrappers.h"
 #include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
 
 #include "mbedtls/platform.h"
 
@@ -1290,4 +1291,344 @@
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 }
+
+
+/*
+ * MAC functions
+ */
+psa_status_t psa_driver_wrapper_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            (void) input;
+            (void) input_length;
+            (void) mac;
+            (void) mac_size;
+            (void) mac_length;
+            (void) status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_sign_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_sign_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx,
+                                                 attributes,
+                                                 key_buffer, key_buffer_size,
+                                                 alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_sign_setup(
+                &operation->ctx.opaque_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) status;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_verify_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_verify_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx,
+                                                   attributes,
+                                                   key_buffer, key_buffer_size,
+                                                   alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_verify_setup(
+                &operation->ctx.opaque_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) status;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_update(
+    psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx,
+                                            input, input_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_update(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        input, input_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) input;
+            (void) input_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_sign_finish(
+    psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx,
+                                                 mac, mac_size, mac_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_sign_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_size, mac_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_sign_finish(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        mac, mac_size, mac_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) mac;
+            (void) mac_size;
+            (void) mac_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_verify_finish(
+    psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx,
+                                                   mac, mac_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_verify_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_verify_finish(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        mac, mac_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) mac;
+            (void) mac_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_mac_abort(
+    psa_mac_operation_t *operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_abort(
+                        &operation->ctx.transparent_test_driver_ctx ) );
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_abort(
+                        &operation->ctx.opaque_test_driver_ctx ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
 /* End of automatically generated file. */
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index e82d093..37d5a9a 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -183,6 +183,53 @@
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
 
+/*
+ * MAC functions
+ */
+psa_status_t psa_driver_wrapper_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t psa_driver_wrapper_mac_sign_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_mac_verify_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_mac_update(
+    psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t psa_driver_wrapper_mac_sign_finish(
+    psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t psa_driver_wrapper_mac_verify_finish(
+    psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t psa_driver_wrapper_mac_abort(
+    psa_mac_operation_t *operation );
+
 #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
 
 /* End of automatically generated file. */
diff --git a/library/psa_crypto_mac.c b/library/psa_crypto_mac.c
new file mode 100644
index 0000000..20c56a0
--- /dev/null
+++ b/library/psa_crypto_mac.c
@@ -0,0 +1,787 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_mac.h"
+#include <mbedtls/md.h>
+
+#include <mbedtls/error.h>
+#include <string.h>
+
+/* Use builtin defines specific to this compilation unit, since the test driver
+ * relies on the software driver. */
+#if( defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \
+    ( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) ) )
+#define BUILTIN_ALG_CMAC        1
+#endif
+#if( defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \
+    ( defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) ) )
+#define BUILTIN_ALG_HMAC        1
+#endif
+
+#if defined(BUILTIN_ALG_HMAC)
+static size_t psa_get_hash_block_size( psa_algorithm_t alg )
+{
+    switch( alg )
+    {
+        case PSA_ALG_MD2:
+            return( 16 );
+        case PSA_ALG_MD4:
+            return( 64 );
+        case PSA_ALG_MD5:
+            return( 64 );
+        case PSA_ALG_RIPEMD160:
+            return( 64 );
+        case PSA_ALG_SHA_1:
+            return( 64 );
+        case PSA_ALG_SHA_224:
+            return( 64 );
+        case PSA_ALG_SHA_256:
+            return( 64 );
+        case PSA_ALG_SHA_384:
+            return( 128 );
+        case PSA_ALG_SHA_512:
+            return( 128 );
+        default:
+            return( 0 );
+    }
+}
+
+static psa_status_t psa_hmac_abort_internal(
+    mbedtls_psa_hmac_operation_t *hmac )
+{
+    mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) );
+    return( psa_hash_abort( &hmac->hash_ctx ) );
+}
+
+static psa_status_t psa_hmac_setup_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t hash_alg )
+{
+    uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    size_t i;
+    size_t hash_size = PSA_HASH_LENGTH( hash_alg );
+    size_t block_size = psa_get_hash_block_size( hash_alg );
+    psa_status_t status;
+
+    hmac->alg = hash_alg;
+
+    /* Sanity checks on block_size, to guarantee that there won't be a buffer
+     * overflow below. This should never trigger if the hash algorithm
+     * is implemented correctly. */
+    /* The size checks against the ipad and opad buffers cannot be written
+     * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
+     * because that triggers -Wlogical-op on GCC 7.3. */
+    if( block_size > sizeof( ipad ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    if( block_size > sizeof( hmac->opad ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    if( block_size < hash_size )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    if( key_length > block_size )
+    {
+        status = psa_hash_compute( hash_alg, key, key_length,
+                                   ipad, sizeof( ipad ), &key_length );
+        if( status != PSA_SUCCESS )
+            goto cleanup;
+    }
+    /* A 0-length key is not commonly used in HMAC when used as a MAC,
+     * but it is permitted. It is common when HMAC is used in HKDF, for
+     * example. Don't call `memcpy` in the 0-length because `key` could be
+     * an invalid pointer which would make the behavior undefined. */
+    else if( key_length != 0 )
+        memcpy( ipad, key, key_length );
+
+    /* ipad contains the key followed by garbage. Xor and fill with 0x36
+     * to create the ipad value. */
+    for( i = 0; i < key_length; i++ )
+        ipad[i] ^= 0x36;
+    memset( ipad + key_length, 0x36, block_size - key_length );
+
+    /* Copy the key material from ipad to opad, flipping the requisite bits,
+     * and filling the rest of opad with the requisite constant. */
+    for( i = 0; i < key_length; i++ )
+        hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
+    memset( hmac->opad + key_length, 0x5C, block_size - key_length );
+
+    status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
+    if( status != PSA_SUCCESS )
+        goto cleanup;
+
+    status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
+
+cleanup:
+    mbedtls_platform_zeroize( ipad, sizeof( ipad ) );
+
+    return( status );
+}
+
+static psa_status_t psa_hmac_update_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    const uint8_t *data,
+    size_t data_length )
+{
+    return( psa_hash_update( &hmac->hash_ctx, data, data_length ) );
+}
+
+static psa_status_t psa_hmac_finish_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    uint8_t *mac,
+    size_t mac_size )
+{
+    uint8_t tmp[MBEDTLS_MD_MAX_SIZE];
+    psa_algorithm_t hash_alg = hmac->alg;
+    size_t hash_size = 0;
+    size_t block_size = psa_get_hash_block_size( hash_alg );
+    psa_status_t status;
+
+    status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
+    if( status != PSA_SUCCESS )
+        return( status );
+    /* From here on, tmp needs to be wiped. */
+
+    status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    memcpy( mac, tmp, mac_size );
+
+exit:
+    mbedtls_platform_zeroize( tmp, hash_size );
+    return( status );
+}
+#endif /* BUILTIN_ALG_HMAC */
+
+#if defined(BUILTIN_ALG_CMAC)
+static psa_status_t cmac_setup( mbedtls_psa_mac_operation_t *operation,
+                                const psa_key_attributes_t *attributes,
+                                const uint8_t *key_buffer )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(PSA_WANT_KEY_TYPE_DES)
+    /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
+     * to do CMAC with pure DES, so return NOT_SUPPORTED here. */
+    if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_DES &&
+        ( psa_get_key_bits( attributes ) == 64 ||
+          psa_get_key_bits( attributes ) == 128 ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+
+    const mbedtls_cipher_info_t * cipher_info =
+        mbedtls_cipher_info_from_psa(
+            PSA_ALG_CMAC,
+            psa_get_key_type( attributes ),
+            psa_get_key_bits( attributes ),
+            NULL );
+
+    if( cipher_info == NULL )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
+    if( ret != 0 )
+        goto exit;
+
+    ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
+                                      key_buffer,
+                                      psa_get_key_bits( attributes ) );
+exit:
+    return( mbedtls_to_psa_error( ret ) );
+}
+#endif /* BUILTIN_ALG_CMAC */
+
+/* Implement the PSA driver MAC interface on top of mbed TLS if either the
+ * software driver or the test driver requires it. */
+#if defined(BUILTIN_ALG_HMAC) || defined(BUILTIN_ALG_CMAC)
+
+/* Initialize this driver's MAC operation structure. Once this function has been
+ * called, mbedtls_psa_mac_abort can run and will do the right thing. */
+static psa_status_t mac_init(
+    mbedtls_psa_mac_operation_t *operation,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    operation->alg = alg;
+
+#if defined(BUILTIN_ALG_CMAC)
+    if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC )
+    {
+        mbedtls_cipher_init( &operation->ctx.cmac );
+        status = PSA_SUCCESS;
+    }
+    else
+#endif /* BUILTIN_ALG_CMAC */
+#if defined(BUILTIN_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( operation->alg ) )
+    {
+        /* We'll set up the hash operation later in psa_hmac_setup_internal. */
+        operation->ctx.hmac.alg = 0;
+        status = PSA_SUCCESS;
+    }
+    else
+#endif /* BUILTIN_ALG_HMAC */
+    {
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if( status != PSA_SUCCESS )
+        memset( operation, 0, sizeof( *operation ) );
+    return( status );
+}
+
+static psa_status_t mac_abort( mbedtls_psa_mac_operation_t *operation )
+{
+    if( operation->alg == 0 )
+    {
+        /* The object has (apparently) been initialized but it is not
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return( PSA_SUCCESS );
+    }
+    else
+#if defined(BUILTIN_ALG_CMAC)
+    if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC )
+    {
+        mbedtls_cipher_free( &operation->ctx.cmac );
+    }
+    else
+#endif /* BUILTIN_ALG_CMAC */
+#if defined(BUILTIN_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( operation->alg ) )
+    {
+        psa_hmac_abort_internal( &operation->ctx.hmac );
+    }
+    else
+#endif /* BUILTIN_ALG_HMAC */
+    {
+        /* Sanity check (shouldn't happen: operation->alg should
+         * always have been initialized to a valid value). */
+        goto bad_state;
+    }
+
+    operation->alg = 0;
+
+    return( PSA_SUCCESS );
+
+bad_state:
+    /* If abort is called on an uninitialized object, we can't trust
+     * anything. Wipe the object in case it contains confidential data.
+     * This may result in a memory leak if a pointer gets overwritten,
+     * but it's too late to do anything about this. */
+    memset( operation, 0, sizeof( *operation ) );
+    return( PSA_ERROR_BAD_STATE );
+}
+
+static psa_status_t mac_setup( mbedtls_psa_mac_operation_t *operation,
+                               const psa_key_attributes_t *attributes,
+                               const uint8_t *key_buffer,
+                               size_t key_buffer_size,
+                               psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* A context must be freshly initialized before it can be set up. */
+    if( operation->alg != 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+    status = mac_init( operation, alg );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+#if defined(BUILTIN_ALG_CMAC)
+    if( PSA_ALG_FULL_LENGTH_MAC( alg ) == PSA_ALG_CMAC )
+    {
+        /* Key buffer size for CMAC is dictated by the key bits set on the
+         * attributes, and previously validated by the core on key import. */
+        (void) key_buffer_size;
+        status = cmac_setup( operation, attributes, key_buffer );
+    }
+    else
+#endif /* BUILTIN_ALG_CMAC */
+#if defined(BUILTIN_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( alg ) )
+    {
+        status = psa_hmac_setup_internal( &operation->ctx.hmac,
+                                          key_buffer,
+                                          key_buffer_size,
+                                          PSA_ALG_HMAC_GET_HASH( alg ) );
+    }
+    else
+#endif /* BUILTIN_ALG_HMAC */
+    {
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if( status != PSA_SUCCESS )
+        mac_abort( operation );
+
+    return( status );
+}
+
+static psa_status_t mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    /* One-shot MAC has not been implemented in this PSA implementation yet. */
+    (void) attributes;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) mac;
+    (void) mac_size;
+    (void) mac_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+static psa_status_t mac_update(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    if( operation->alg == 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+#if defined(BUILTIN_ALG_CMAC)
+    if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC )
+    {
+        return( mbedtls_to_psa_error(
+                    mbedtls_cipher_cmac_update( &operation->ctx.cmac,
+                                                input, input_length ) ) );
+    }
+    else
+#endif /* BUILTIN_ALG_CMAC */
+#if defined(BUILTIN_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( operation->alg ) )
+    {
+        return( psa_hmac_update_internal( &operation->ctx.hmac,
+                                          input, input_length ) );
+    }
+    else
+#endif /* BUILTIN_ALG_HMAC */
+    {
+        /* This shouldn't happen if `operation` was initialized by
+         * a setup function. */
+        (void) input;
+        (void) input_length;
+        return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static psa_status_t mac_finish_internal( mbedtls_psa_mac_operation_t *operation,
+                                         uint8_t *mac,
+                                         size_t mac_size )
+{
+#if defined(BUILTIN_ALG_CMAC)
+    if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC )
+    {
+        uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
+        int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp );
+        if( ret == 0 )
+            memcpy( mac, tmp, mac_size );
+        mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+        return( mbedtls_to_psa_error( ret ) );
+    }
+    else
+#endif /* BUILTIN_ALG_CMAC */
+#if defined(BUILTIN_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( operation->alg ) )
+    {
+        return( psa_hmac_finish_internal( &operation->ctx.hmac,
+                                          mac, mac_size ) );
+    }
+    else
+#endif /* BUILTIN_ALG_HMAC */
+    {
+        /* This shouldn't happen if `operation` was initialized by
+         * a setup function. */
+        (void) operation;
+        (void) mac;
+        (void) mac_size;
+        return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static psa_status_t mac_sign_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->alg == 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+    status = mac_finish_internal( operation, mac, mac_size );
+
+    if( status == PSA_SUCCESS )
+        *mac_length = mac_size;
+
+    return( status );
+}
+
+static psa_status_t mac_verify_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    uint8_t actual_mac[PSA_MAC_MAX_SIZE];
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->alg == 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+    /* Consistency check: requested MAC length fits our local buffer */
+    if( mac_length > sizeof( actual_mac ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    status = mac_finish_internal( operation, actual_mac, mac_length );
+    if( status != PSA_SUCCESS )
+        goto cleanup;
+
+    if( mbedtls_psa_safer_memcmp( mac, actual_mac, mac_length ) != 0 )
+        status = PSA_ERROR_INVALID_SIGNATURE;
+
+cleanup:
+    mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
+
+    return( status );
+}
+#endif /* BUILTIN_ALG_HMAC || BUILTIN_ALG_CMAC */
+
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+psa_status_t mbedtls_psa_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    return( mac_compute( attributes, key_buffer, key_buffer_size, alg,
+                         input, input_length,
+                         mac, mac_size, mac_length ) );
+}
+
+psa_status_t mbedtls_psa_mac_sign_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    return( mac_setup( operation, attributes,
+                       key_buffer, key_buffer_size, alg ) );
+}
+
+psa_status_t mbedtls_psa_mac_verify_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    return( mac_setup( operation, attributes,
+                       key_buffer, key_buffer_size, alg ) );
+}
+
+psa_status_t mbedtls_psa_mac_update(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    return( mac_update( operation, input, input_length ) );
+}
+
+psa_status_t mbedtls_psa_mac_sign_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    return( mac_sign_finish( operation, mac, mac_size, mac_length ) );
+}
+
+psa_status_t mbedtls_psa_mac_verify_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    return( mac_verify_finish( operation, mac, mac_length ) );
+}
+
+psa_status_t mbedtls_psa_mac_abort(
+    mbedtls_psa_mac_operation_t *operation )
+{
+    return( mac_abort( operation ) );
+}
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+ /*
+  * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
+  */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+static int is_mac_accelerated( psa_algorithm_t alg )
+{
+#if defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
+    if( PSA_ALG_IS_HMAC( alg ) )
+        return( 1 );
+#endif
+
+    switch( PSA_ALG_FULL_LENGTH_MAC( alg ) )
+    {
+#if defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)
+        case PSA_ALG_CMAC:
+            return( 1 );
+#endif
+        default:
+            return( 0 );
+    }
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    if( is_mac_accelerated( alg ) )
+        return( mac_compute( attributes, key_buffer, key_buffer_size, alg,
+                             input, input_length,
+                             mac, mac_size, mac_length ) );
+    else
+        return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_sign_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    if( is_mac_accelerated( alg ) )
+        return( mac_setup( operation, attributes,
+                           key_buffer, key_buffer_size, alg ) );
+    else
+        return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_verify_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    if( is_mac_accelerated( alg ) )
+        return( mac_setup( operation, attributes,
+                           key_buffer, key_buffer_size, alg ) );
+    else
+        return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    if( is_mac_accelerated( operation->alg ) )
+        return( mac_update( operation, input, input_length ) );
+    else
+        return( PSA_ERROR_BAD_STATE );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    if( is_mac_accelerated( operation->alg ) )
+        return( mac_sign_finish( operation, mac, mac_size, mac_length ) );
+    else
+        return( PSA_ERROR_BAD_STATE );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    if( is_mac_accelerated( operation->alg ) )
+        return( mac_verify_finish( operation, mac, mac_length ) );
+    else
+        return( PSA_ERROR_BAD_STATE );
+}
+
+psa_status_t mbedtls_transparent_test_driver_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation )
+{
+    return( mac_abort( operation ) );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) attributes;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) mac;
+    (void) mac_size;
+    (void) mac_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_sign_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    (void) attributes;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_verify_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    (void) attributes;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    (void) input;
+    (void) input_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    (void) mac;
+    (void) mac_size;
+    (void) mac_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    (void) mac;
+    (void) mac_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_opaque_test_driver_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation )
+{
+    /* Opaque driver testing is not implemented yet through this mechanism. */
+    (void) operation;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_mac.h b/library/psa_crypto_mac.h
new file mode 100644
index 0000000..9b81e73
--- /dev/null
+++ b/library/psa_crypto_mac.h
@@ -0,0 +1,372 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_MAC_H
+#define PSA_CRYPTO_MAC_H
+
+#include <psa/crypto.h>
+
+/** Calculate the MAC (message authentication code) of a message using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_compute
+ *       entry point. This function behaves as a mac_compute entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ * \param[in] input             Buffer containing the input message.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] mac              Buffer where the MAC value is to be written.
+ * \param mac_size              Size of the \p mac buffer in bytes.
+ * \param[out] mac_length       On success, the number of bytes
+ *                              that make up the MAC value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p mac_size is too small
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length);
+
+/** Set up a multipart MAC calculation operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_sign_setup
+ *       entry point. This function behaves as a mac_sign_setup entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be inactive).
+ */
+psa_status_t mbedtls_psa_mac_sign_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Set up a multipart MAC verification operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_verify_setup
+ *       entry point. This function behaves as a mac_verify_setup entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be inactive).
+ */
+psa_status_t mbedtls_psa_mac_verify_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart MAC operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_update
+ *       entry point. This function behaves as a mac_update entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_sign_setup() or
+ * mbedtls_psa_mac_verify_setup() before calling this function.
+ *
+ * If this function returns an error status, the PSA core aborts the
+ * operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] input         Buffer containing the message fragment to add to
+ *                          the MAC calculation.
+ * \param 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).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_update(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+/** Finish the calculation of the MAC of a message using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_sign_finish
+ *       entry point. This function behaves as a mac_sign_finish entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to mbedtls_psa_mac_update().
+ *
+ * Whether this function returns successfully or not, the PSA core subsequently
+ * aborts the operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[out] mac          Buffer where the MAC value is to be written.
+ * \param mac_size          Output size requested for the MAC algorithm. The PSA
+ *                          core guarantees this is a valid MAC length for the
+ *                          algorithm and key combination passed to
+ *                          mbedtls_psa_mac_sign_setup(). It also guarantees the
+ *                          \p mac buffer is large enough to contain the
+ *                          requested output size.
+ * \param[out] mac_length   On success, the number of bytes output to buffer
+ *                          \p mac, which will be equal to the requested length
+ *                          \p mac_size.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be an active mac sign
+ *         operation).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p mac buffer is too small. A sufficient buffer size
+ *         can be determined by calling PSA_MAC_LENGTH().
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_sign_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+/** Finish the calculation of the MAC of a message and compare it with
+ * an expected value using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       mac_verify_finish entry point. This function behaves as a
+ *       mac_verify_finish entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this
+ * function. This function calculates the MAC of the message formed by
+ * concatenating the inputs passed to preceding calls to
+ * mbedtls_psa_mac_update(). It then compares the calculated MAC with the
+ * expected MAC passed as a parameter to this function.
+ *
+ * Whether this function returns successfully or not, the PSA core subsequently
+ * aborts the operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] mac           Buffer containing the expected MAC value.
+ * \param mac_length        Length in bytes of the expected MAC value. The PSA
+ *                          core guarantees that this length is a valid MAC
+ *                          length for the algorithm and key combination passed
+ *                          to mbedtls_psa_mac_verify_setup().
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected MAC is identical to the actual MAC of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The MAC of the message was calculated successfully, but it
+ *         differs from the expected MAC.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be an active mac verify
+ *         operation).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_verify_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+/** Abort a MAC operation using Mbed TLS.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again.
+ *
+ * The PSA core may call this function any time after the operation object has
+ * been initialized by one of the methods described in
+ * #mbedtls_psa_mac_operation_t.
+ *
+ * In particular, calling mbedtls_psa_mac_abort() after the operation has been
+ * terminated by a call to mbedtls_psa_mac_abort(),
+ * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and
+ * has no effect.
+ *
+ * \param[in,out] operation Initialized MAC operation.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_abort(
+    mbedtls_psa_mac_operation_t *operation );
+
+/*
+ * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
+ */
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+psa_status_t mbedtls_transparent_test_driver_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_transparent_test_driver_mac_sign_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_transparent_test_driver_mac_verify_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_transparent_test_driver_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_transparent_test_driver_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_transparent_test_driver_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_transparent_test_driver_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation );
+
+psa_status_t mbedtls_opaque_test_driver_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_opaque_test_driver_mac_sign_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_opaque_test_driver_mac_verify_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_opaque_test_driver_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_opaque_test_driver_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_opaque_test_driver_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_opaque_test_driver_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+#endif /* PSA_CRYPTO_MAC_H */
diff --git a/programs/psa/psa_constant_names.c b/programs/psa/psa_constant_names.c
index 14d4494..b5fea04 100644
--- a/programs/psa/psa_constant_names.c
+++ b/programs/psa/psa_constant_names.c
@@ -52,12 +52,6 @@
 }
 #endif
 
-/* There are different GET_HASH macros for different kinds of algorithms
- * built from hashes, but the values are all constructed on the
- * same model. */
-#define PSA_ALG_GET_HASH(alg)                                   \
-    (((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH)
-
 static void append(char **buffer, size_t buffer_size,
                    size_t *required_size,
                    const char *string, size_t length)
diff --git a/programs/psa/psa_constant_names_generated.c b/programs/psa/psa_constant_names_generated.c
index dcbe87f..bcb95f8 100644
--- a/programs/psa/psa_constant_names_generated.c
+++ b/programs/psa/psa_constant_names_generated.c
@@ -113,6 +113,9 @@
     case PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE", 32); break;
     case PSA_KEY_TYPE_HMAC: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_HMAC", 17); break;
     case PSA_KEY_TYPE_NONE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_NONE", 17); break;
+    case PSA_KEY_TYPE_PASSWORD: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_PASSWORD", 21); break;
+    case PSA_KEY_TYPE_PASSWORD_HASH: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_PASSWORD_HASH", 26); break;
+    case PSA_KEY_TYPE_PEPPER: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_PEPPER", 19); break;
     case PSA_KEY_TYPE_RAW_DATA: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RAW_DATA", 21); break;
     case PSA_KEY_TYPE_RSA_KEY_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RSA_KEY_PAIR", 25); break;
     case PSA_KEY_TYPE_RSA_PUBLIC_KEY: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RSA_PUBLIC_KEY", 27); break;
@@ -221,6 +224,8 @@
     case PSA_ALG_MD4: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD4", 11); break;
     case PSA_ALG_MD5: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD5", 11); break;
     case PSA_ALG_OFB: append(&buffer, buffer_size, &required_size, "PSA_ALG_OFB", 11); break;
+    case PSA_ALG_PBKDF2_AES_CMAC_PRF_128: append(&buffer, buffer_size, &required_size, "PSA_ALG_PBKDF2_AES_CMAC_PRF_128", 31); break;
+    case PSA_ALG_PBKDF2_HMAC_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_PBKDF2_HMAC_BASE", 24); break;
     case PSA_ALG_PURE_EDDSA: append(&buffer, buffer_size, &required_size, "PSA_ALG_PURE_EDDSA", 18); break;
     case PSA_ALG_RIPEMD160: append(&buffer, buffer_size, &required_size, "PSA_ALG_RIPEMD160", 17); break;
     case PSA_ALG_RSA_OAEP_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_OAEP_BASE", 21); break;
@@ -286,6 +291,13 @@
                             psa_hash_algorithm_name,
                             PSA_ALG_GET_HASH(core_alg));
             append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_PBKDF2_HMAC(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_PBKDF2_HMAC(", 19 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
         } else if (PSA_ALG_IS_RSA_OAEP(core_alg)) {
             append(&buffer, buffer_size, &required_size,
                    "PSA_ALG_RSA_OAEP(", 16 + 1);
@@ -394,6 +406,13 @@
         append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_HASH", 23);
         usage ^= PSA_KEY_USAGE_SIGN_HASH;
     }
+    if (usage & PSA_KEY_USAGE_VERIFY_DERIVATION) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_DERIVATION", 31);
+        usage ^= PSA_KEY_USAGE_VERIFY_DERIVATION;
+    }
     if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
         if (required_size != 0) {
             append(&buffer, buffer_size, &required_size, " | ", 3);
diff --git a/scripts/mbedtls_dev/crypto_knowledge.py b/scripts/mbedtls_dev/crypto_knowledge.py
index 500acea..aa52790 100644
--- a/scripts/mbedtls_dev/crypto_knowledge.py
+++ b/scripts/mbedtls_dev/crypto_knowledge.py
@@ -89,6 +89,9 @@
         'PSA_KEY_TYPE_DERIVE': (120, 128), # sample
         'PSA_KEY_TYPE_DES': (64, 128, 192), # exhaustive
         'PSA_KEY_TYPE_HMAC': (128, 160, 224, 256, 384, 512), # standard size for each supported hash
+        'PSA_KEY_TYPE_PASSWORD': (48, 168, 336), # sample
+        'PSA_KEY_TYPE_PASSWORD_HASH': (128, 256), # sample
+        'PSA_KEY_TYPE_PEPPER': (128, 256), # sample
         'PSA_KEY_TYPE_RAW_DATA': (8, 40, 128), # sample
         'PSA_KEY_TYPE_RSA_KEY_PAIR': (1024, 1536), # small sample
     }
diff --git a/tests/include/test/drivers/mac.h b/tests/include/test/drivers/mac.h
new file mode 100644
index 0000000..7733dd3
--- /dev/null
+++ b/tests/include/test/drivers/mac.h
@@ -0,0 +1,141 @@
+/*
+ * Test driver for MAC driver entry points.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_TEST_DRIVERS_MAC_H
+#define PSA_CRYPTO_TEST_DRIVERS_MAC_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times MAC driver functions are called. */
+    unsigned long hits;
+    /* Status returned by the last MAC driver function call. */
+    psa_status_t driver_status;
+} mbedtls_test_driver_mac_hooks_t;
+
+#define MBEDTLS_TEST_DRIVER_MAC_INIT { 0, 0, 0 }
+static inline mbedtls_test_driver_mac_hooks_t
+    mbedtls_test_driver_mac_hooks_init( void )
+{
+    const mbedtls_test_driver_mac_hooks_t v = MBEDTLS_TEST_DRIVER_MAC_INIT;
+    return( v );
+}
+
+extern mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks;
+
+psa_status_t mbedtls_test_transparent_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_transparent_mac_sign_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_transparent_mac_verify_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_transparent_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_transparent_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_transparent_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_test_transparent_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation );
+
+psa_status_t mbedtls_test_opaque_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_opaque_mac_sign_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_opaque_mac_verify_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_opaque_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_opaque_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_opaque_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_test_opaque_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_MAC_H */
diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h
index dc2136a..5b60932 100644
--- a/tests/include/test/drivers/test_driver.h
+++ b/tests/include/test/drivers/test_driver.h
@@ -25,6 +25,7 @@
 #include "test/drivers/aead.h"
 #include "test/drivers/cipher.h"
 #include "test/drivers/hash.h"
+#include "test/drivers/mac.h"
 #include "test/drivers/key_management.h"
 #include "test/drivers/signature.h"
 #include "test/drivers/size.h"
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index a4d50c1..8b9d7d1 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1438,6 +1438,8 @@
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_384"
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_512"
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_XTS"
+    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CMAC"
+    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_HMAC"
     loc_cflags="${loc_cflags} -I../tests/include -O2"
 
     make CC=gcc CFLAGS="$loc_cflags" LDFLAGS="$ASAN_CFLAGS"
@@ -2235,6 +2237,8 @@
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_384"
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_512"
     loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_XTS"
+    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CMAC"
+    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_HMAC"
     loc_cflags="${loc_cflags} -I../tests/include -O2"
 
     make CC=gcc CFLAGS="${loc_cflags}" LDFLAGS="$ASAN_CFLAGS"
diff --git a/tests/src/drivers/test_driver_mac.c b/tests/src/drivers/test_driver_mac.c
new file mode 100644
index 0000000..69af107
--- /dev/null
+++ b/tests/src/drivers/test_driver_mac.c
@@ -0,0 +1,362 @@
+/*
+ * Test driver for MAC entry points.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa_crypto_mac.h"
+
+#include "test/drivers/mac.h"
+
+mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks =
+    MBEDTLS_TEST_DRIVER_MAC_INIT;
+
+psa_status_t mbedtls_test_transparent_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_sign_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_sign_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_verify_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_verify_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_update(
+                operation, input, input_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_sign_finish(
+                operation, mac, mac_size, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_verify_finish(
+                operation, mac, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_transparent_test_driver_mac_abort( operation );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_sign_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_sign_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_verify_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_verify_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_update(
+                operation, input, input_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_sign_finish(
+                operation, mac, mac_size, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_verify_finish(
+                operation, mac, mac_length );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_opaque_test_driver_mac_abort( operation );
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 944ef23..7b86185 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1294,6 +1294,22 @@
 depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 4):"4869205468657265":"87aa7cde"
 
+PSA MAC sign: CMAC-3DES (CAVP vector #95)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_sign:PSA_KEY_TYPE_DES:"7c34e67a2a8fef581cc4f7dceaea130dad52c189739e401f":PSA_ALG_CMAC:"eb3365a0a9d141270334065547418fe64c47823c024082b94d54a66d149f2af1":"e1d7c3736739e726"
+
+PSA MAC verify: CMAC-3DES (CAVP vector #95)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_verify:PSA_KEY_TYPE_DES:"7c34e67a2a8fef581cc4f7dceaea130dad52c189739e401f":PSA_ALG_CMAC:"eb3365a0a9d141270334065547418fe64c47823c024082b94d54a66d149f2af1":"e1d7c3736739e726"
+
+PSA MAC: CMAC-3DES-2key (not supported in PSA)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_setup:PSA_KEY_TYPE_DES:"89fe91f1c1ef2f01efc4c18f5715894c":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC: CMAC-DES (not supported in PSA)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_setup:PSA_KEY_TYPE_DES:"89fe91f1c1ef2f01":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+
 PSA MAC sign: CMAC-AES-128
 depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 5fbfac6..95ab688 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -197,7 +197,7 @@
 cipher_entry_points:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_SUCCESS
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, fallback
@@ -205,11 +205,11 @@
 aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_NOT_SUPPORTED
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, INSUFFICIENT_MEMORY
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_INSUFFICIENT_MEMORY
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_SUCCESS
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1, fallback
@@ -217,11 +217,11 @@
 aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_NOT_SUPPORTED
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1, INSUFFICIENT_MEMORY
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_INSUFFICIENT_MEMORY
 
 PSA AEAD decrypt: AES-CCM, 39 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 39 bytes, fallback
@@ -229,11 +229,11 @@
 aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_NOT_SUPPORTED
 
 PSA AEAD decrypt: AES-CCM, 39 bytes, INSUFFICIENT_MEMORY
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_INSUFFICIENT_MEMORY
 
 PSA AEAD decrypt, AES-GCM, 144 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, 144 bytes #1, fallback
@@ -241,31 +241,87 @@
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_NOT_SUPPORTED
 
 PSA AEAD decrypt, AES-GCM, 144 bytes #1, INSUFFICIENT_MEMORY
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_INSUFFICIENT_MEMORY
 
+PSA MAC sign, through driver: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_ACCEL_ALG_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_SUCCESS
+
+PSA MAC sign, fallback: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_BUILTIN_ALG_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC sign, driver reports error: RFC4231 Test case 1 - HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC sign, through driver: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_ACCEL_ALG_CMAC
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_SUCCESS
+
+PSA MAC sign, fallback: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_ALG_CMAC
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC sign, driver reports error: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC verify, through driver: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_ACCEL_ALG_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_SUCCESS
+
+PSA MAC verify, fallback: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_BUILTIN_ALG_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC verify, driver reports error: RFC4231 Test case 1 - HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC verify, through driver: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_ACCEL_ALG_CMAC
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_SUCCESS
+
+PSA MAC verify, fallback: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_ALG_CMAC
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC verify, driver reports error: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_GENERIC_ERROR
+
 PSA opaque driver builtin key export: AES
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
 
 PSA opaque driver builtin key export: AES (registered to ID_MAX-1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX - 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
 
 PSA opaque driver builtin key export: AES (registered to ID_MAX)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
 
 PSA opaque driver builtin key export: key ID out of range (ID_MIN - 1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_ERROR_INVALID_HANDLE
 
 PSA opaque driver builtin key export: key ID out of range (ID_MAX + 1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX + 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_ERROR_INVALID_HANDLE
 
 PSA opaque driver builtin key export: secp256r1
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
 builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"dc7d9d26d67a4f632c34c2dc0b6986183882c206df04cdb7d69aabe28be4f81a":PSA_SUCCESS
 
 PSA opaque driver builtin pubkey export: secp256r1
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
 builtin_pubkey_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"0485f64d89f00be66c88dd937efd6d7c445648dcb701150b8a9509295850f41c1931e571fb8f8c78317a20b380e866584bbc2516c3d2702d792f131a922095fd6c":PSA_SUCCESS
 
 PSA opaque driver builtin pubkey export: not a public key
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
 builtin_pubkey_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"0485f64d89f00be66c88dd937efd6d7c445648dcb701150b8a9509295850f41c1931e571fb8f8c78317a20b380e866584bbc2516c3d2702d792f131a922095fd6c":PSA_ERROR_INVALID_ARGUMENT
 
 Hash compute: SHA-256, computed by the driver
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index a0b719e..ac241f5 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -963,6 +963,197 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void mac_sign( int key_type_arg,
+               data_t *key_data,
+               int alg_arg,
+               data_t *input,
+               data_t *expected_mac,
+               int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t *actual_mac = NULL;
+    size_t mac_buffer_size =
+        PSA_MAC_LENGTH( key_type, PSA_BYTES_TO_BITS( key_data->len ), alg );
+    size_t mac_length = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t forced_status = forced_status_arg;
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+
+    TEST_ASSERT( mac_buffer_size <= PSA_MAC_MAX_SIZE );
+    /* We expect PSA_MAC_LENGTH to be exact. */
+    TEST_ASSERT( expected_mac->len == mac_buffer_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    ASSERT_ALLOC( actual_mac, mac_buffer_size );
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /* Calculate the MAC. */
+    status = psa_mac_sign_setup( &operation, key, alg );
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    status = psa_mac_update( &operation,
+                             input->x, input->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 2 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    status = psa_mac_sign_finish( &operation,
+                                  actual_mac, mac_buffer_size,
+                                  &mac_length );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    PSA_ASSERT( psa_mac_abort( &operation ) );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_mac->x, expected_mac->len,
+                        actual_mac, mac_length );
+    }
+
+    mbedtls_free( actual_mac );
+    actual_mac = NULL;
+
+exit:
+    psa_mac_abort( &operation );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_free( actual_mac );
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_verify( int key_type_arg,
+                 data_t *key_data,
+                 int alg_arg,
+                 data_t *input,
+                 data_t *expected_mac,
+                 int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t forced_status = forced_status_arg;
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+
+    TEST_ASSERT( expected_mac->len <= PSA_MAC_MAX_SIZE );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /* Test the correct MAC. */
+    status = psa_mac_verify_setup( &operation, key, alg );
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    status = psa_mac_update( &operation,
+                             input->x, input->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 2 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    status = psa_mac_verify_finish( &operation,
+                                    expected_mac->x,
+                                    expected_mac->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+
+    PSA_ASSERT( psa_mac_abort( &operation ) );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+exit:
+    psa_mac_abort( &operation );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:PSA_CRYPTO_DRIVER_TEST:MBEDTLS_PSA_CRYPTO_DRIVERS:MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 void builtin_key_export( int builtin_key_id_arg,
                          int builtin_key_type_arg,
diff --git a/tests/suites/test_suite_psa_crypto_not_supported.generated.data b/tests/suites/test_suite_psa_crypto_not_supported.generated.data
index e39c8ed..23ce19f 100644
--- a/tests/suites/test_suite_psa_crypto_not_supported.generated.data
+++ b/tests/suites/test_suite_psa_crypto_not_supported.generated.data
@@ -152,6 +152,62 @@
 depends_on:!PSA_WANT_KEY_TYPE_HMAC
 generate_not_supported:PSA_KEY_TYPE_HMAC:512
 
+PSA import PASSWORD 48-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PASSWORD:"486572650069"
+
+PSA generate PASSWORD 48-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PASSWORD:48
+
+PSA import PASSWORD 168-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PASSWORD:"48657265006973206b6579a0646174614865726500"
+
+PSA generate PASSWORD 168-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PASSWORD:168
+
+PSA import PASSWORD 336-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PASSWORD:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b65"
+
+PSA generate PASSWORD 336-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PASSWORD:336
+
+PSA import PASSWORD_HASH 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD_HASH:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PASSWORD_HASH:"48657265006973206b6579a064617461"
+
+PSA generate PASSWORD_HASH 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD_HASH:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PASSWORD_HASH:128
+
+PSA import PASSWORD_HASH 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD_HASH:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PASSWORD_HASH:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate PASSWORD_HASH 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PASSWORD_HASH:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PASSWORD_HASH:256
+
+PSA import PEPPER 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PEPPER:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PEPPER:"48657265006973206b6579a064617461"
+
+PSA generate PEPPER 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PEPPER:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PEPPER:128
+
+PSA import PEPPER 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PEPPER:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_PEPPER:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate PEPPER 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_PEPPER:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_PEPPER:256
+
 PSA import RSA_KEY_PAIR 1024-bit not supported
 depends_on:!PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 import_not_supported:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
diff --git a/tests/suites/test_suite_psa_crypto_storage_format.current.data b/tests/suites/test_suite_psa_crypto_storage_format.current.data
index f74d0e2..732b80b 100644
--- a/tests/suites/test_suite_psa_crypto_storage_format.current.data
+++ b/tests/suites/test_suite_psa_crypto_storage_format.current.data
@@ -28,6 +28,10 @@
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001000000000000000000000010000004b"
 
+PSA storage save: usage: VERIFY_DERIVATION
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_DERIVATION:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800008000000000000000000000010000004b"
+
 PSA storage save: usage: VERIFY_HASH
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002000000000000000000000010000004b"
@@ -52,9 +56,13 @@
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800011000000000000000000000010000004b"
 
-PSA storage save: usage: SIGN_HASH | VERIFY_HASH
+PSA storage save: usage: SIGN_HASH | VERIFY_DERIVATION
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
-key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800003000000000000000000000010000004b"
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800009000000000000000000000010000004b"
+
+PSA storage save: usage: VERIFY_DERIVATION | VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b45590000000000010000000110080000a000000000000000000000010000004b"
 
 PSA storage save: usage: VERIFY_HASH | COPY
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
@@ -62,7 +70,7 @@
 
 PSA storage save: usage: all known
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
-key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800037300000000000000000000010000004b"
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b45590000000000010000000110080003f300000000000000000000010000004b"
 
 PSA storage save: type: AES 128-bit
 depends_on:PSA_WANT_KEY_TYPE_AES
@@ -148,6 +156,34 @@
 depends_on:PSA_WANT_KEY_TYPE_HMAC
 key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100020100000000000000000000004000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
 
+PSA storage save: type: PASSWORD 48-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_save:0x0001:PSA_KEY_TYPE_PASSWORD:48:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"486572650069":"505341004b45590000000000010000000312300001000000000000000000000006000000486572650069"
+
+PSA storage save: type: PASSWORD 168-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_save:0x0001:PSA_KEY_TYPE_PASSWORD:168:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500":"505341004b45590000000000010000000312a8000100000000000000000000001500000048657265006973206b6579a0646174614865726500"
+
+PSA storage save: type: PASSWORD 336-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_save:0x0001:PSA_KEY_TYPE_PASSWORD:336:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b65":"505341004b4559000000000001000000031250010100000000000000000000002a00000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b65"
+
+PSA storage save: type: PASSWORD_HASH 128-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD_HASH
+key_storage_save:0x0001:PSA_KEY_TYPE_PASSWORD_HASH:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000051280000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: PASSWORD_HASH 256-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD_HASH
+key_storage_save:0x0001:PSA_KEY_TYPE_PASSWORD_HASH:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000051200010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: PEPPER 128-bit
+depends_on:PSA_WANT_KEY_TYPE_PEPPER
+key_storage_save:0x0001:PSA_KEY_TYPE_PEPPER:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000061280000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: PEPPER 256-bit
+depends_on:PSA_WANT_KEY_TYPE_PEPPER
+key_storage_save:0x0001:PSA_KEY_TYPE_PEPPER:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000061200010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
 PSA storage save: type: RAW_DATA 8-bit
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000011008000100000000000000000000000100000048"
@@ -584,6 +620,14 @@
 depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_OFB:"4c":"505341004b45590000000000010000000110080001000000000000000012c004010000004c"
 
+PSA storage save: alg: PSA_ALG_PBKDF2_AES_CMAC_PRF_128
+depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:0x0000:"4b":"505341004b455900000000000100000001100800010000000002800800000000010000004b"
+
+PSA storage save: alg2: PSA_ALG_PBKDF2_AES_CMAC_PRF_128
+depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:"4c":"505341004b455900000000000100000001100800010000000000000000028008010000004c"
+
 PSA storage save: alg: PSA_ALG_PURE_EDDSA
 depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PURE_EDDSA:0x0000:"4b":"505341004b455900000000000100000001100800010000000008000600000000010000004b"
diff --git a/tests/suites/test_suite_psa_crypto_storage_format.v0.data b/tests/suites/test_suite_psa_crypto_storage_format.v0.data
index 2b2f1b7..82f55dd 100644
--- a/tests/suites/test_suite_psa_crypto_storage_format.v0.data
+++ b/tests/suites/test_suite_psa_crypto_storage_format.v0.data
@@ -28,6 +28,10 @@
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001000000000000000000000010000004b":0
 
+PSA storage read: usage: VERIFY_DERIVATION
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_DERIVATION:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800008000000000000000000000010000004b":0
+
 PSA storage read: usage: VERIFY_HASH
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002000000000000000000000010000004b":0
@@ -52,9 +56,13 @@
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800011000000000000000000000010000004b":0
 
-PSA storage read: usage: SIGN_HASH | VERIFY_HASH
+PSA storage read: usage: SIGN_HASH | VERIFY_DERIVATION
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
-key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800003000000000000000000000010000004b":0
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800009000000000000000000000010000004b":0
+
+PSA storage read: usage: VERIFY_DERIVATION | VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b45590000000000010000000110080000a000000000000000000000010000004b":0
 
 PSA storage read: usage: VERIFY_HASH | COPY
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
@@ -62,7 +70,7 @@
 
 PSA storage read: usage: all known
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
-key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800037300000000000000000000010000004b":0
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b45590000000000010000000110080003f300000000000000000000010000004b":0
 
 PSA storage read: type: AES 128-bit
 depends_on:PSA_WANT_KEY_TYPE_AES
@@ -148,6 +156,34 @@
 depends_on:PSA_WANT_KEY_TYPE_HMAC
 key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100020100000000000000000000004000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":1
 
+PSA storage read: type: PASSWORD 48-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_read:0x0001:PSA_KEY_TYPE_PASSWORD:48:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"486572650069":"505341004b45590000000000010000000312300001000000000000000000000006000000486572650069":1
+
+PSA storage read: type: PASSWORD 168-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_read:0x0001:PSA_KEY_TYPE_PASSWORD:168:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500":"505341004b45590000000000010000000312a8000100000000000000000000001500000048657265006973206b6579a0646174614865726500":1
+
+PSA storage read: type: PASSWORD 336-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD
+key_storage_read:0x0001:PSA_KEY_TYPE_PASSWORD:336:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b65":"505341004b4559000000000001000000031250010100000000000000000000002a00000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b65":1
+
+PSA storage read: type: PASSWORD_HASH 128-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD_HASH
+key_storage_read:0x0001:PSA_KEY_TYPE_PASSWORD_HASH:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000051280000100000000000000000000001000000048657265006973206b6579a064617461":1
+
+PSA storage read: type: PASSWORD_HASH 256-bit
+depends_on:PSA_WANT_KEY_TYPE_PASSWORD_HASH
+key_storage_read:0x0001:PSA_KEY_TYPE_PASSWORD_HASH:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000051200010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":1
+
+PSA storage read: type: PEPPER 128-bit
+depends_on:PSA_WANT_KEY_TYPE_PEPPER
+key_storage_read:0x0001:PSA_KEY_TYPE_PEPPER:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000061280000100000000000000000000001000000048657265006973206b6579a064617461":1
+
+PSA storage read: type: PEPPER 256-bit
+depends_on:PSA_WANT_KEY_TYPE_PEPPER
+key_storage_read:0x0001:PSA_KEY_TYPE_PEPPER:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000061200010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":1
+
 PSA storage read: type: RAW_DATA 8-bit
 depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000011008000100000000000000000000000100000048":0
@@ -584,6 +620,14 @@
 depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_OFB:"4c":"505341004b45590000000000010000000110080001000000000000000012c004010000004c":0
 
+PSA storage read: alg: PSA_ALG_PBKDF2_AES_CMAC_PRF_128
+depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:0x0000:"4b":"505341004b455900000000000100000001100800010000000002800800000000010000004b":0
+
+PSA storage read: alg2: PSA_ALG_PBKDF2_AES_CMAC_PRF_128
+depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:"4c":"505341004b455900000000000100000001100800010000000000000000028008010000004c":0
+
 PSA storage read: alg: PSA_ALG_PURE_EDDSA
 depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
 key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PURE_EDDSA:0x0000:"4b":"505341004b455900000000000100000001100800010000000008000600000000010000004b":0
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 26950b1..c2f1063 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -207,11 +207,13 @@
     <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />

     <ClInclude Include="..\..\include\mbedtls\xtea.h" />

     <ClInclude Include="..\..\include\psa\crypto.h" />

-    <ClInclude Include="..\..\include\psa\crypto_builtin.h" />

+    <ClInclude Include="..\..\include\psa\crypto_builtin_composites.h" />

+    <ClInclude Include="..\..\include\psa\crypto_builtin_primitives.h" />

     <ClInclude Include="..\..\include\psa\crypto_compat.h" />

     <ClInclude Include="..\..\include\psa\crypto_config.h" />

     <ClInclude Include="..\..\include\psa\crypto_driver_common.h" />

-    <ClInclude Include="..\..\include\psa\crypto_driver_contexts.h" />

+    <ClInclude Include="..\..\include\psa\crypto_driver_contexts_composites.h" />

+    <ClInclude Include="..\..\include\psa\crypto_driver_contexts_primitives.h" />

     <ClInclude Include="..\..\include\psa\crypto_extra.h" />

     <ClInclude Include="..\..\include\psa\crypto_platform.h" />

     <ClInclude Include="..\..\include\psa\crypto_se_driver.h" />

@@ -233,6 +235,7 @@
     <ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\hash.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\key_management.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\mac.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\size.h" />

     <ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />

@@ -259,6 +262,7 @@
     <ClInclude Include="..\..\library\psa_crypto_hash.h" />

     <ClInclude Include="..\..\library\psa_crypto_invasive.h" />

     <ClInclude Include="..\..\library\psa_crypto_its.h" />

+    <ClInclude Include="..\..\library\psa_crypto_mac.h" />

     <ClInclude Include="..\..\library\psa_crypto_random_impl.h" />

     <ClInclude Include="..\..\library\psa_crypto_rsa.h" />

     <ClInclude Include="..\..\library\psa_crypto_se.h" />

@@ -334,6 +338,7 @@
     <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />

     <ClCompile Include="..\..\library\psa_crypto_ecp.c" />

     <ClCompile Include="..\..\library\psa_crypto_hash.c" />

+    <ClCompile Include="..\..\library\psa_crypto_mac.c" />

     <ClCompile Include="..\..\library\psa_crypto_rsa.c" />

     <ClCompile Include="..\..\library\psa_crypto_se.c" />

     <ClCompile Include="..\..\library\psa_crypto_slot_management.c" />

@@ -379,6 +384,7 @@
     <ClCompile Include="..\..\tests\src\drivers\test_driver_aead.c" />

     <ClCompile Include="..\..\tests\src\drivers\test_driver_cipher.c" />

     <ClCompile Include="..\..\tests\src\drivers\test_driver_key_management.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_mac.c" />

     <ClCompile Include="..\..\tests\src\drivers\test_driver_signature.c" />

     <ClCompile Include="..\..\tests\src\drivers\test_driver_size.c" />

     <ClCompile Include="..\..\3rdparty\everest\library\everest.c" />