From e8f0e3dc3c1c97cdb0d850118aa9a29a2dad9747 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 18 Sep 2018 11:52:10 +0200 Subject: [PATCH] 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. --- include/psa/crypto.h | 35 ++++++++- tests/suites/test_suite_psa_crypto.data | 6 +- .../test_suite_psa_crypto_metadata.data | 2 + .../test_suite_psa_crypto_metadata.function | 71 ++++++++++++++----- 4 files changed, 94 insertions(+), 20 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6efaa0242..f344e1467 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -603,6 +603,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000) +#define PSA_ALG_CATEGORY_KEY_SELECTION ((psa_algorithm_t)0x31000000) #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) @@ -674,6 +675,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) +#define PSA_ALG_KEY_SELECTION_FLAG ((psa_algorithm_t)0x01000000) /** Whether the specified algorithm is a key agreement algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). @@ -683,7 +685,8 @@ typedef uint32_t psa_algorithm_t; * algorithm identifier. */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + (((alg) & PSA_ALG_CATEGORY_MASK & ~PSA_ALG_KEY_SELECTION_FLAG) == \ + PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a key derivation algorithm. * @@ -696,6 +699,17 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) +/** Whether the specified algorithm is a key selection algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key selection 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_SELECTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION) + #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) #define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) #define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) @@ -1185,6 +1199,25 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x010fffff) + +/** Use a shared secret as is. + * + * Specify this algorithm as the selection component of a key agreement + * to use the raw result of the key agreement as key material. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It can however be used as the secret + * input in a key derivation algorithm. + */ +#define PSA_ALG_SELECT_RAW ((psa_algorithm_t)0x31000001) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + ((alg) & ~PSA_ALG_KEY_DERIVATION_MASK) /**@}*/ /** \defgroup key_management Key management diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 229fa81c5..5759a15df 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1377,7 +1377,11 @@ PSA key derivation: bad key type 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 c9df6c74e..09544f4fb 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -242,6 +242,8 @@ Key derivation: HKDF using SHA-256 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 215110a32..4faa4341e 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -107,6 +107,7 @@ void mac_algorithm_core( psa_algorithm_t alg, int classification_flags, 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 @@ void aead_algorithm_core( psa_algorithm_t alg, int classification_flags, 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 @@ void hash_algorithm( int alg_arg, int length_arg ) 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 @@ void cipher_algorithm( int alg_arg, int classification_flags ) 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 @@ void asymmetric_signature_algorithm( int alg_arg, int classification_flags ) 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 @@ void asymmetric_encryption_algorithm( int alg_arg, int classification_flags ) 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,10 +355,57 @@ void key_derivation_algorithm( int alg_arg, int classification_flags ) 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 ) {