Merge pull request #7547 from silabs-Kusumit/PBKDF2_input_validation

PBKDF2: Input Validation
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index a351060..3a2f06e 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -268,6 +268,15 @@
 #define MBEDTLS_SHA512_C
 #endif
 
+#if defined(PSA_WANT_ALG_PBKDF2_HMAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)
+#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
+#endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
+#endif /* PSA_WANT_ALG_PBKDF2_HMAC */
+
 #if defined(PSA_WANT_ALG_TLS12_PRF)
 #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)
 #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
diff --git a/include/psa/crypto_builtin_key_derivation.h b/include/psa/crypto_builtin_key_derivation.h
index 1913a9b..d54291f 100644
--- a/include/psa/crypto_builtin_key_derivation.h
+++ b/include/psa/crypto_builtin_key_derivation.h
@@ -105,5 +105,23 @@
 } psa_tls12_prf_key_derivation_t;
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+typedef enum {
+    PSA_PBKDF2_STATE_INIT,             /* no input provided */
+    PSA_PBKDF2_STATE_INPUT_COST_SET,   /* input cost has been set */
+    PSA_PBKDF2_STATE_SALT_SET,         /* salt has been set */
+    PSA_PBKDF2_STATE_PASSWORD_SET,     /* password has been set */
+    PSA_PBKDF2_STATE_OUTPUT            /* output has been started */
+} psa_pbkdf2_key_derivation_state_t;
+
+typedef struct {
+    psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state);
+    uint64_t MBEDTLS_PRIVATE(input_cost);
+    uint8_t *MBEDTLS_PRIVATE(salt);
+    size_t MBEDTLS_PRIVATE(salt_length);
+    uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    size_t MBEDTLS_PRIVATE(password_length);
+} psa_pbkdf2_key_derivation_t;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
 
 #endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index c08a860..48e20c2 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -75,9 +75,7 @@
 #define PSA_WANT_ALG_HMAC                       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_PBKDF2_HMAC                1
 #define PSA_WANT_ALG_RIPEMD160                  1
 #define PSA_WANT_ALG_RSA_OAEP                   1
 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
@@ -93,8 +91,7 @@
 #define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS       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 */
+/* Note: when adding support, also adjust include/mbedtls/config_psa.h */
 //#define PSA_WANT_ALG_XTS                        1
 
 #define PSA_WANT_ECC_BRAINPOOL_P_R1_256         1
diff --git a/include/psa/crypto_driver_contexts_key_derivation.h b/include/psa/crypto_driver_contexts_key_derivation.h
index 39754cc..5b4e474 100644
--- a/include/psa/crypto_driver_contexts_key_derivation.h
+++ b/include/psa/crypto_driver_contexts_key_derivation.h
@@ -55,6 +55,9 @@
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
     psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);
 #endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2);
+#endif
 } psa_driver_key_derivation_context_t;
 
 #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
index 8fd91ff..75d6582 100644
--- a/include/psa/crypto_sizes.h
+++ b/include/psa/crypto_sizes.h
@@ -261,6 +261,10 @@
  * curve. */
 #define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32
 
+/* The maximum number of iterations for PBKDF2 on this implementation, in bits.
+ * This is a vendor-specific macro. This can be configured if necessary */
+#define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffff
+
 /** The maximum size of a block cipher. */
 #define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16
 
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 39acd96..580e3ae 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -2102,7 +2102,8 @@
  */
 #define PSA_ALG_IS_PBKDF2_HMAC(alg)                                    \
     (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE)
-
+#define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg)                         \
+    (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK))
 /** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm.
  *
  * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 2bd4df1..81427ac 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -5030,7 +5030,8 @@
 #if defined(BUILTIN_ALG_ANY_HKDF) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
 #define AT_LEAST_ONE_BUILTIN_KDF
 #endif /* At least one builtin KDF */
 
@@ -5134,6 +5135,17 @@
                                  sizeof(operation->ctx.tls12_ecjpake_to_pms.data));
     } else
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        if (operation->ctx.pbkdf2.salt != NULL) {
+            mbedtls_platform_zeroize(operation->ctx.pbkdf2.salt,
+                                     operation->ctx.pbkdf2.salt_length);
+            mbedtls_free(operation->ctx.pbkdf2.salt);
+        }
+
+        status = PSA_SUCCESS;
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) */
     {
         status = PSA_ERROR_BAD_STATE;
     }
@@ -5513,6 +5525,15 @@
             &operation->ctx.tls12_ecjpake_to_pms, output, output_length);
     } else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        /* As output functionality is not added yet return
+         * PSA_ERROR_NOT_SUPPORTED for now if inputs are passed correctly.
+         * If input validation fails operation is aborted and output_bytes
+         * will return PSA_ERROR_BAD_STATE */
+        status = PSA_ERROR_NOT_SUPPORTED;
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
 
     {
         (void) kdf_alg;
@@ -5931,6 +5952,11 @@
         return 1;
     }
 #endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        return 1;
+    }
+#endif
     return 0;
 }
 
@@ -6424,6 +6450,130 @@
     return PSA_SUCCESS;
 }
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+static psa_status_t psa_pbkdf2_set_input_cost(
+    psa_pbkdf2_key_derivation_t *pbkdf2,
+    psa_key_derivation_step_t step,
+    uint64_t data)
+{
+    if (step != PSA_KEY_DERIVATION_INPUT_COST) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (data == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    pbkdf2->input_cost = data;
+    pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                        const uint8_t *data,
+                                        size_t data_length)
+{
+    if (pbkdf2->state != PSA_PBKDF2_STATE_INPUT_COST_SET &&
+        pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) {
+        pbkdf2->salt = mbedtls_calloc(1, data_length);
+        if (pbkdf2->salt == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(pbkdf2->salt, data, data_length);
+        pbkdf2->salt_length = data_length;
+    } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) {
+        uint8_t *next_salt;
+
+        next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length);
+        if (next_salt == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length);
+        memcpy(next_salt + pbkdf2->salt_length, data, data_length);
+        pbkdf2->salt_length += data_length;
+        mbedtls_free(pbkdf2->salt);
+        pbkdf2->salt = next_salt;
+    }
+
+    pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg,
+                                                 const uint8_t *input,
+                                                 size_t input_len,
+                                                 uint8_t *output,
+                                                 size_t *output_len)
+{
+    psa_status_t status = PSA_SUCCESS;
+    if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {
+        status = psa_hash_compute(hash_alg, input, input_len, output,
+                                  PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
+    } else {
+        memcpy(output, input, input_len);
+        *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    }
+    return status;
+}
+
+static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                            psa_algorithm_t kdf_alg,
+                                            const uint8_t *data,
+                                            size_t data_length)
+{
+    psa_status_t status = PSA_SUCCESS;
+    if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length != 0) {
+        if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+            psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg);
+            status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length,
+                                                  pbkdf2->password,
+                                                  &pbkdf2->password_length);
+        }
+    }
+
+    pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET;
+
+    return status;
+}
+
+static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                     psa_algorithm_t kdf_alg,
+                                     psa_key_derivation_step_t step,
+                                     const uint8_t *data,
+                                     size_t data_length)
+{
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SALT:
+            return psa_pbkdf2_set_salt(pbkdf2, data, data_length);
+        case PSA_KEY_DERIVATION_INPUT_PASSWORD:
+            return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length);
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
+
 /** Check whether the given key type is acceptable for the given
  * input step of a key derivation.
  *
@@ -6465,6 +6615,17 @@
                 return PSA_SUCCESS;
             }
             break;
+        case PSA_KEY_DERIVATION_INPUT_PASSWORD:
+            if (key_type == PSA_KEY_TYPE_PASSWORD) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_DERIVE) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_NONE) {
+                return PSA_SUCCESS;
+            }
+            break;
     }
     return PSA_ERROR_INVALID_ARGUMENT;
 }
@@ -6508,6 +6669,12 @@
             &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length);
     } else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg,
+                                  step, data, data_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
     {
         /* This can't happen unless the operation object was not initialized */
         (void) data;
@@ -6531,6 +6698,12 @@
     psa_status_t status;
     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
 
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        status = psa_pbkdf2_set_input_cost(
+            &operation->ctx.pbkdf2, step, value);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
     {
         (void) step;
         (void) value;
@@ -6579,9 +6752,10 @@
         return status;
     }
 
-    /* Passing a key object as a SECRET input unlocks the permission
-     * to output to a key object. */
-    if (step == PSA_KEY_DERIVATION_INPUT_SECRET) {
+    /* Passing a key object as a SECRET or PASSWORD input unlocks the
+     * permission to output to a key object. */
+    if (step == PSA_KEY_DERIVATION_INPUT_SECRET ||
+        step == PSA_KEY_DERIVATION_INPUT_PASSWORD) {
         operation->can_output_key = 1;
     }
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 8d3c042..a83140d 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -5467,6 +5467,79 @@
 depends_on:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
 derive_input:PSA_ALG_TLS12_ECJPAKE_TO_PMS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"04aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ERROR_INVALID_ARGUMENT:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
+PSA key derivation: PBKDF2-HMAC-SHA256, good case, direct output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_PASSWORD:"706173737764":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, good case, key output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_PASSWORD:"706173737764":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, good case, DERIVE key as password, key output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_DERIVE:"706173737764":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, input cost greater than PSA_VENDOR_PBKDF2_MAX_ITERATIONS
+#Input cost is passed as hex number. Value of PSA_VENDOR_PBKDF2_MAX_ITERATIONS is 0xffffffff
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"0100000000":PSA_ERROR_NOT_SUPPORTED:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_DERIVE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, salt missing
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_PASSWORD:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, password missing
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, salt and password before cost
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_PASSWORD:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, password before cost
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_PASSWORD:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, password bad key type
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_RAW_DATA:"706173737764":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, direct password, direct output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, direct empty password, direct output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, direct password, key output
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, DERIVE key as salt
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_DERIVE:"73616c74":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, duplicate cost step
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, duplicate salt step
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_COST:INPUT_INTEGER:"01":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: PBKDF2-HMAC-SHA256, reject secret step
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, reject label step
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: PBKDF2-HMAC-SHA256, reject seed step
+depends_on:PSA_WANT_ALG_PBKDF2_HMAC:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"73616c74":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_PASSWORD:PSA_KEY_TYPE_NONE:"706173737764":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
 PSA key derivation over capacity: HKDF
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_over_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256)