New algorithm category: key selection

A key selection algorithm is similar to a key derivation algorithm in
that it takes a secret input and produces a secret output stream.
However, unlike key derivation algorithms, there is no expectation
that the input cannot be reconstructed from the output. Key selection
algorithms are exclusively meant to be used on the output of a key
agreement algorithm to select chunks of the shared secret.
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 229fa81..5759a15 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1377,7 +1377,11 @@
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
 derive_setup:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HKDF(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT
 
-PSA key derivation: not a key derivation algorithm
+PSA key derivation: not a key derivation algorithm (selection)
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_SELECT_RAW:"":"":42:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key derivation: not a key derivation algorithm (HMAC)
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
 derive_setup:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"":"":42:PSA_ERROR_INVALID_ARGUMENT
 
diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data
index c9df6c7..09544f4 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.data
+++ b/tests/suites/test_suite_psa_crypto_metadata.data
@@ -242,6 +242,8 @@
 depends_on:MBEDTLS_SHA256_C
 key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):ALG_IS_HKDF
 
+Key selection: raw
+key_selection_algorithm:PSA_ALG_SELECT_RAW:0
 Key type: raw data
 key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED
 
diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function
index 215110a..4faa434 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.function
+++ b/tests/suites/test_suite_psa_crypto_metadata.function
@@ -107,6 +107,7 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 
     /* Length */
@@ -127,6 +128,7 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 
     /* Tag length */
@@ -166,6 +168,7 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, 0 );
 
     /* Dependent algorithms */
@@ -262,6 +265,7 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 }
 /* END_CASE */
@@ -313,6 +317,7 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 }
 /* END_CASE */
@@ -331,24 +336,7 @@
     TEST_ASSERT( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
-    algorithm_classification( alg, classification_flags );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void key_agreement_algorithm( int alg_arg, int classification_flags )
-{
-    psa_algorithm_t alg = alg_arg;
-
-    /* Algorithm classification */
-    TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
-    TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( alg ) );
-    TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 }
 /* END_CASE */
@@ -367,11 +355,58 @@
     TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
     TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
     TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
     algorithm_classification( alg, classification_flags );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
+void key_selection_algorithm( int alg_arg, int classification_flags )
+{
+    psa_algorithm_t alg = alg_arg;
+
+    /* Algorithm classification */
+    TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( PSA_ALG_IS_KEY_SELECTION( alg ) );
+    algorithm_classification( alg, classification_flags );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_agreement_algorithm( int alg_arg, int classification_flags,
+                              int post_alg_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_algorithm_t actual_post_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg );
+    psa_algorithm_t expected_post_alg = post_alg_arg;
+
+    /* Algorithm classification */
+    TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) );
+    TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) );
+    TEST_ASSERT( ! PSA_ALG_IS_KEY_SELECTION( alg ) );
+    algorithm_classification( alg, classification_flags );
+
+    /* Shared secret derivation properties */
+    TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( actual_post_alg ) ||
+                 PSA_ALG_IS_KEY_SELECTION( actual_post_alg ) );
+    TEST_ASSERT( actual_post_alg == expected_post_alg );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void key_type( int type_arg, int classification_flags )
 {
     psa_key_type_t type = type_arg;