From e6d3edaf327ec3097ad18f442df42b0369d90556 Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Thu, 26 Aug 2021 11:46:14 +0200 Subject: [PATCH 01/13] Add missing PSA_ALG_IS_SIGN_HASH macro. Signed-off-by: Mateusz Starzyk --- include/psa/crypto.h | 8 ++++++-- include/psa/crypto_values.h | 15 +++++++++++++++ library/psa_crypto.c | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 5d9854a7ba..ee4b54cbf9 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -2990,7 +2990,9 @@ psa_status_t psa_verify_message( mbedtls_svc_key_id_t key, * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_HASH. - * \param alg A signature algorithm that is compatible with + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. @@ -3043,7 +3045,9 @@ psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, * must be a public key or an asymmetric key pair. The * key must allow the usage * #PSA_KEY_USAGE_VERIFY_HASH. - * \param alg A signature algorithm that is compatible with + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message whose signature is to be * verified. diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 621b872fc8..526b4549d2 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1621,6 +1621,21 @@ #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) || (alg) == PSA_ALG_PURE_EDDSA ) +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_hash() and psa_verify_hash(). + * + * \param alg An algorithm identifier (value of type psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * hash. 0 if alg is a signature algorithm that can only be used + * to sign a message. 0 if alg is not a signature algorithm. + * This macro can return either 0 or 1 if alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) || (alg) == PSA_ALG_ED25519PH || \ + (alg) == PSA_ALG_ED448PH) + /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3670071a5d..84b85667cc 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -2652,7 +2652,7 @@ static psa_status_t psa_sign_verify_check_alg( int input_is_message, } else { - if( ! PSA_ALG_IS_HASH_AND_SIGN( alg ) ) + if( ! PSA_ALG_IS_SIGN_HASH( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); } From 359b5ab6eaa5ff6fcfee6e88cc445db129bc37af Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Thu, 26 Aug 2021 12:52:56 +0200 Subject: [PATCH 02/13] Add missing PSA_ALG_NONE macro. Signed-off-by: Mateusz Starzyk --- include/psa/crypto_values.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 526b4549d2..9ce8b68780 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -847,6 +847,9 @@ (PSA_ALG_IS_KEY_DERIVATION(alg) && \ (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) +/** An invalid algorithm identifier value. */ +#define PSA_ALG_NONE ((psa_algorithm_t)0) + #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) /** MD5 */ #define PSA_ALG_MD5 ((psa_algorithm_t)0x02000003) From 7d262dd1ee62e62942928428846470c12f5de93d Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Thu, 26 Aug 2021 13:28:46 +0200 Subject: [PATCH 03/13] Add missing PSA_HASH_BLOCK_LENGTH macro. Signed-off-by: Mateusz Starzyk --- include/psa/crypto_sizes.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 4c67f10afa..5f230e0f0f 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -79,6 +79,38 @@ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ 0) +/** The input block size of a hash algorithm, in bytes. + * + * Hash algorithms process their input data in blocks. Hash operations will + * retain any partial blocks until they have enough input to fill the block or + * until the operation is finished. + * This affects the output from psa_hash_suspend(). + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * PSA_ALG_IS_HASH(\p alg) is true). + * + * \return The block size in bytes for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation can return either 0 or the correct size for a + * hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_BLOCK_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 : \ + 0) + /** \def PSA_HASH_MAX_SIZE * * Maximum size of a hash. From c5c5b9361102de706ae66b054408e93f89b95121 Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Thu, 26 Aug 2021 13:32:30 +0200 Subject: [PATCH 04/13] Add missing PSA_KEY_ID_NULL macro. Signed-off-by: Mateusz Starzyk --- include/psa/crypto_values.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 9ce8b68780..252c29590d 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2150,6 +2150,9 @@ #define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t)0x800000) +/** The null key identifier. + */ +#define PSA_KEY_ID_NULL ((psa_key_id_t)0) /** The minimum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) From 5bc9bf7584f7bb1d3ef35f854803a1fb1ac84563 Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Thu, 26 Aug 2021 14:29:02 +0200 Subject: [PATCH 05/13] Add changelog entry for new PSA Crypto API macros. Signed-off-by: Mateusz Starzyk --- ChangeLog.d/psa_crypto_api_macros.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ChangeLog.d/psa_crypto_api_macros.txt diff --git a/ChangeLog.d/psa_crypto_api_macros.txt b/ChangeLog.d/psa_crypto_api_macros.txt new file mode 100644 index 0000000000..c695ff5c95 --- /dev/null +++ b/ChangeLog.d/psa_crypto_api_macros.txt @@ -0,0 +1,3 @@ +Features + * Add missing PSA macros declared by PSA Crypto API 1.0.0: + PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL From e7be73d5794f26c15920adbb53d3f6f31be17a22 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 22 Sep 2021 14:44:28 +0200 Subject: [PATCH 06/13] Use the new macro PSA_HASH_BLOCK_LENGTH Replace an equivalent internal function. Signed-off-by: Gilles Peskine --- library/psa_crypto_mac.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/library/psa_crypto_mac.c b/library/psa_crypto_mac.c index 2c079d434f..7e0a8325df 100644 --- a/library/psa_crypto_mac.c +++ b/library/psa_crypto_mac.c @@ -42,29 +42,6 @@ #endif #if defined(BUILTIN_ALG_HMAC) -static size_t psa_get_hash_block_size( psa_algorithm_t alg ) -{ - switch( alg ) - { - 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 ) { @@ -81,7 +58,7 @@ static psa_status_t psa_hmac_setup_internal( 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 ); + size_t block_size = PSA_HASH_BLOCK_LENGTH( hash_alg ); psa_status_t status; hmac->alg = hash_alg; @@ -153,7 +130,7 @@ static psa_status_t psa_hmac_finish_internal( 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 ); + size_t block_size = PSA_HASH_BLOCK_LENGTH( hash_alg ); psa_status_t status; status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); From c1ec49eb13d0b0769ce610dcf1248282bb5ed43a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 22 Sep 2021 14:47:26 +0200 Subject: [PATCH 07/13] Test PSA_HASH_BLOCK_LENGTH Only tested for algorithms for which we support HMAC, since that's all we use PSA_HASH_BLOCK_LENGTH for at the moment. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_psa_crypto_metadata.function | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index ab9b2f879a..d868f5903d 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -353,6 +353,7 @@ void hmac_algorithm( int alg_arg, TEST_ASSERT( PSA_ALG_IS_HASH( hash_alg ) ); TEST_EQUAL( PSA_ALG_HMAC( hash_alg ), alg ); + TEST_ASSERT( block_size == PSA_HASH_BLOCK_LENGTH( alg ) ); TEST_ASSERT( block_size <= PSA_HMAC_MAX_HASH_BLOCK_SIZE ); test_mac_algorithm( alg_arg, ALG_IS_HMAC, length, From f7b4137e69e494c9e40b4620f7567775bf44bab3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 22 Sep 2021 16:15:05 +0200 Subject: [PATCH 08/13] Untangle PSA_ALG_IS_HASH_AND_SIGN and PSA_ALG_IS_SIGN_HASH The current definition of PSA_ALG_IS_HASH_AND_SIGN includes PSA_ALG_RSA_PKCS1V15_SIGN_RAW and PSA_ALG_ECDSA_ANY, which don't strictly follow the hash-and-sign paradigm: the algorithm does not encode a hash algorithm that is applied prior to the signature step. The definition in fact encompasses what can be used with psa_sign_hash/psa_verify_hash, so it's the correct definition for PSA_ALG_IS_SIGN_HASH. Therefore this commit moves definition of PSA_ALG_IS_HASH_AND_SIGN to PSA_ALG_IS_SIGN_HASH, and replace the definition of PSA_ALG_IS_HASH_AND_SIGN by a correct one (based on PSA_ALG_IS_SIGN_HASH, excluding the algorithms where the pre-signature step isn't to apply the hash encoded in the algorithm). In the definition of PSA_ALG_SIGN_GET_HASH, keep the condition for a nonzero output to be PSA_ALG_IS_HASH_AND_SIGN. Everywhere else in the code base (definition of PSA_ALG_IS_SIGN_MESSAGE, and every use of PSA_ALG_IS_HASH_AND_SIGN outside of crypto_values.h), we meant PSA_ALG_IS_SIGN_HASH where we wrote PSA_ALG_IS_HASH_AND_SIGN, so do a global replacement. ``` git grep -l IS_HASH_AND_SIGN ':!include/psa/crypto_values.h' | xargs perl -i -pe 's/ALG_IS_HASH_AND_SIGN/ALG_IS_SIGN_HASH/g' ``` Signed-off-by: Gilles Peskine --- include/psa/crypto_values.h | 34 ++++++++++++++----- library/psa_crypto.c | 12 +++---- tests/src/psa_exercise_key.c | 4 +-- tests/suites/test_suite_psa_crypto.function | 2 +- .../test_suite_psa_crypto_metadata.data | 18 +++++----- .../test_suite_psa_crypto_metadata.function | 6 ++-- 6 files changed, 47 insertions(+), 29 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 252c29590d..cb40d4e442 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1597,7 +1597,20 @@ * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms * structured in two parts: first the calculation of a hash in a way that * does not depend on the key, then the calculation of a signature from the - * hash value and the key. + * hash value and the key. Hash-and-sign algorithms encode the hash + * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH + * to extract this algorithm. + * + * Thus, for a hash-and-sign algorithm, + * `psa_sign_message(key, alg, input, ...)` is equivalent to + * ``` + * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...); + * psa_sign_hash(key, alg, hash, ..., signature, ...); + * ``` + * Most usefully, separating the hash from the signature allows the hash + * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to + * calculating the hash and then calling psa_verify_hash(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * @@ -1606,9 +1619,8 @@ * algorithm identifier. */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ - PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) + (PSA_ALG_IS_SIGN_HASH(alg) && \ + ((alg) & PSA_ALG_HASH_MASK) != 0) /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_message() and psa_verify_message(). @@ -1622,11 +1634,17 @@ * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) || (alg) == PSA_ALG_PURE_EDDSA ) + (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA ) /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_hash() and psa_verify_hash(). * + * This encompasses all strict hash-and-sign algorithms categorized by + * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the + * paradigm more loosely: + * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) + * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) + * * \param alg An algorithm identifier (value of type psa_algorithm_t). * * \return 1 if alg is a signature algorithm that can be used to sign a @@ -1636,8 +1654,9 @@ * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_HASH(alg) \ - (PSA_ALG_IS_HASH_AND_SIGN(alg) || (alg) == PSA_ALG_ED25519PH || \ - (alg) == PSA_ALG_ED448PH) + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ + PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) /** Get the hash used by a hash-and-sign signature algorithm. * @@ -1659,7 +1678,6 @@ */ #define PSA_ALG_SIGN_GET_HASH(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 84b85667cc..c4bcddcb1a 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -623,8 +623,8 @@ static psa_algorithm_t psa_key_policy_algorithm_intersection( return( alg1 ); /* If the policies are from the same hash-and-sign family, check * if one is a wildcard. If so the other has the specific algorithm. */ - if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) && - PSA_ALG_IS_HASH_AND_SIGN( alg2 ) && + if( PSA_ALG_IS_SIGN_HASH( alg1 ) && + PSA_ALG_IS_SIGN_HASH( alg2 ) && ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) { if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) @@ -726,7 +726,7 @@ static int psa_key_algorithm_permits( psa_key_type_t key_type, /* If policy_alg is a hash-and-sign with a wildcard for the hash, * and requested_alg is the same hash-and-sign family with any hash, * then requested_alg is compliant with policy_alg. */ - if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) && + if( PSA_ALG_IS_SIGN_HASH( requested_alg ) && PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH ) { return( ( policy_alg & ~PSA_ALG_HASH_MASK ) == @@ -2644,7 +2644,7 @@ static psa_status_t psa_sign_verify_check_alg( int input_is_message, if( ! PSA_ALG_IS_SIGN_MESSAGE( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); - if ( PSA_ALG_IS_HASH_AND_SIGN( alg ) ) + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) { if( ! PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( alg ) ) ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -2802,7 +2802,7 @@ psa_status_t psa_sign_message_builtin( { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if ( PSA_ALG_IS_HASH_AND_SIGN( alg ) ) + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; @@ -2849,7 +2849,7 @@ psa_status_t psa_verify_message_builtin( { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if ( PSA_ALG_IS_HASH_AND_SIGN( alg ) ) + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c index 923d2c136a..91bac678ef 100644 --- a/tests/src/psa_exercise_key.c +++ b/tests/src/psa_exercise_key.c @@ -306,7 +306,7 @@ static int exercise_signature_key( mbedtls_svc_key_id_t key, psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); /* If the policy allows signing with any hash, just pick one. */ - if( PSA_ALG_IS_HASH_AND_SIGN( alg ) && hash_alg == PSA_ALG_ANY_HASH ) + if( PSA_ALG_IS_SIGN_HASH( alg ) && hash_alg == PSA_ALG_ANY_HASH ) { #if defined(KNOWN_SUPPORTED_HASH_ALG) hash_alg = KNOWN_SUPPORTED_HASH_ALG; @@ -925,7 +925,7 @@ psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type, { if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) ) { - if( PSA_ALG_IS_HASH_AND_SIGN( alg ) ) + if( PSA_ALG_IS_SIGN_HASH( alg ) ) { if( PSA_ALG_SIGN_GET_HASH( alg ) ) return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ? diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 591c2960de..01a06989df 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1422,7 +1422,7 @@ void asymmetric_signature_key_policy( int policy_usage_arg, else TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED ); - if( PSA_ALG_IS_HASH_AND_SIGN( exercise_alg ) && + if( PSA_ALG_IS_SIGN_HASH( exercise_alg ) && PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( exercise_alg ) ) ) { status = psa_sign_message( key, exercise_alg, diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index ad806c77cc..d6758fabae 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -196,31 +196,31 @@ aead_algorithm:PSA_ALG_CHACHA20_POLY1305:0:16:PSA_KEY_TYPE_CHACHA20:256 Asymmetric signature: RSA PKCS#1 v1.5 raw depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN -asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH Asymmetric signature: RSA PKCS#1 v1.5 SHA-256 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH Asymmetric signature: RSA PSS SHA-256 depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT | ALG_IS_SIGN_HASH Asymmetric signature: RSA PSS-any-salt SHA-256 depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT | ALG_IS_SIGN_HASH Asymmetric signature: randomized ECDSA (no hashing) depends_on:PSA_WANT_ALG_ECDSA -asymmetric_signature_algorithm:PSA_ALG_ECDSA_ANY:ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_ECDSA_ANY:ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH Asymmetric signature: SHA-256 + randomized ECDSA depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH Asymmetric signature: SHA-256 + deterministic ECDSA using SHA-256 depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_SIGN_HASH Asymmetric signature: pure EdDSA depends_on:PSA_WANT_ALG_EDDSA @@ -228,11 +228,11 @@ asymmetric_signature_algorithm:PSA_ALG_PURE_EDDSA:0 Asymmetric signature: Ed25519ph depends_on:PSA_WANT_ALG_EDDSA -asymmetric_signature_algorithm:PSA_ALG_ED25519PH:ALG_IS_HASH_EDDSA | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_ED25519PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH Asymmetric signature: Ed448ph depends_on:PSA_WANT_ALG_EDDSA -asymmetric_signature_algorithm:PSA_ALG_ED448PH:ALG_IS_HASH_EDDSA | ALG_IS_HASH_AND_SIGN +asymmetric_signature_algorithm:PSA_ALG_ED448PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH Asymmetric signature: RSA PKCS#1 v1.5 with wildcard hash depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index d868f5903d..e64dc39477 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -33,7 +33,7 @@ #define ALG_IS_DETERMINISTIC_ECDSA ( 1u << 14 ) #define ALG_IS_RANDOMIZED_ECDSA ( 1u << 15 ) #define ALG_IS_HASH_EDDSA ( 1u << 16 ) -#define ALG_IS_HASH_AND_SIGN ( 1u << 17 ) +#define ALG_IS_SIGN_HASH ( 1u << 17 ) #define ALG_IS_RSA_OAEP ( 1u << 18 ) #define ALG_IS_HKDF ( 1u << 19 ) #define ALG_IS_FFDH ( 1u << 20 ) @@ -114,7 +114,7 @@ void algorithm_classification( psa_algorithm_t alg, unsigned flags ) TEST_CLASSIFICATION_MACRO( ALG_IS_DETERMINISTIC_ECDSA, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_ECDSA, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_EDDSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_AND_SIGN, alg, flags ); + TEST_CLASSIFICATION_MACRO( ALG_IS_SIGN_HASH, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_OAEP, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_HKDF, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_WILDCARD, alg, flags ); @@ -490,7 +490,7 @@ void asymmetric_signature_algorithm( int alg_arg, int classification_flags ) /* BEGIN_CASE */ void asymmetric_signature_wildcard( int alg_arg, int classification_flags ) { - classification_flags |= ALG_IS_HASH_AND_SIGN | ALG_IS_WILDCARD; + classification_flags |= ALG_IS_SIGN_HASH | ALG_IS_WILDCARD; test_asymmetric_signature_algorithm( alg_arg, classification_flags ); /* Any failure of this test function comes from * asymmetric_signature_algorithm. Pacify -Werror=unused-label. */ From f2fe31ab4e39bc633d8c35703bb4c2ca47127f57 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 22 Sep 2021 16:42:02 +0200 Subject: [PATCH 09/13] Reorder macro definitions Definition before mention Signed-off-by: Gilles Peskine --- include/psa/crypto_values.h | 72 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index cb40d4e442..f0d76fb557 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1592,6 +1592,42 @@ * file. */ #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_hash() and psa_verify_hash(). + * + * This encompasses all strict hash-and-sign algorithms categorized by + * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the + * paradigm more loosely: + * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) + * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) + * + * \param alg An algorithm identifier (value of type psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * hash. 0 if alg is a signature algorithm that can only be used + * to sign a message. 0 if alg is not a signature algorithm. + * This macro can return either 0 or 1 if alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_HASH(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ + PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) + +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_message() and psa_verify_message(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * message. 0 if \p alg is a signature algorithm that can only be used + * to sign an already-calculated hash. 0 if \p alg is not a signature + * algorithm. This macro can return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_MESSAGE(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA ) + /** Whether the specified algorithm is a hash-and-sign algorithm. * * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms @@ -1622,42 +1658,6 @@ (PSA_ALG_IS_SIGN_HASH(alg) && \ ((alg) & PSA_ALG_HASH_MASK) != 0) -/** Whether the specified algorithm is a signature algorithm that can be used - * with psa_sign_message() and psa_verify_message(). - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if alg is a signature algorithm that can be used to sign a - * message. 0 if \p alg is a signature algorithm that can only be used - * to sign an already-calculated hash. 0 if \p alg is not a signature - * algorithm. This macro can return either 0 or 1 if \p alg is not a - * supported algorithm identifier. - */ -#define PSA_ALG_IS_SIGN_MESSAGE(alg) \ - (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA ) - -/** Whether the specified algorithm is a signature algorithm that can be used - * with psa_sign_hash() and psa_verify_hash(). - * - * This encompasses all strict hash-and-sign algorithms categorized by - * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the - * paradigm more loosely: - * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) - * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) - * - * \param alg An algorithm identifier (value of type psa_algorithm_t). - * - * \return 1 if alg is a signature algorithm that can be used to sign a - * hash. 0 if alg is a signature algorithm that can only be used - * to sign a message. 0 if alg is not a signature algorithm. - * This macro can return either 0 or 1 if alg is not a - * supported algorithm identifier. - */ -#define PSA_ALG_IS_SIGN_HASH(alg) \ - (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ - PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) - /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is From 4977e9fe64ab468be1fa8ae3059820116c36235b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 22 Sep 2021 18:12:31 +0200 Subject: [PATCH 10/13] Add PSA_ALG_IS_HASH_AND_SIGN to the metadata tests The status of signature wildcards with respect to PSA_ALG_IS_HASH_AND_SIGN is unclear in the specification. A wildcard is usually instantiated with a specific hash, making the implementation hash-and-sign, but it could also be instantiated with a non-hash-and-sign algorithm. For the time being, go with what's currently implemented, which is that they are considered hash-and-sign. Signed-off-by: Gilles Peskine --- .../test_suite_psa_crypto_metadata.data | 14 +++++----- .../test_suite_psa_crypto_metadata.function | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index d6758fabae..83763c55d9 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -200,15 +200,15 @@ asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:ALG_IS_RSA_PKCS1V15 Asymmetric signature: RSA PKCS#1 v1.5 SHA-256 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: RSA PSS SHA-256 depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: RSA PSS-any-salt SHA-256 depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: randomized ECDSA (no hashing) depends_on:PSA_WANT_ALG_ECDSA @@ -216,11 +216,11 @@ asymmetric_signature_algorithm:PSA_ALG_ECDSA_ANY:ALG_IS_ECDSA | ALG_IS_RANDOMIZE Asymmetric signature: SHA-256 + randomized ECDSA depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: SHA-256 + deterministic ECDSA using SHA-256 depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256 -asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: pure EdDSA depends_on:PSA_WANT_ALG_EDDSA @@ -228,11 +228,11 @@ asymmetric_signature_algorithm:PSA_ALG_PURE_EDDSA:0 Asymmetric signature: Ed25519ph depends_on:PSA_WANT_ALG_EDDSA -asymmetric_signature_algorithm:PSA_ALG_ED25519PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_ED25519PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: Ed448ph depends_on:PSA_WANT_ALG_EDDSA -asymmetric_signature_algorithm:PSA_ALG_ED448PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH +asymmetric_signature_algorithm:PSA_ALG_ED448PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN Asymmetric signature: RSA PKCS#1 v1.5 with wildcard hash depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index e64dc39477..0f2fcec590 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -33,16 +33,17 @@ #define ALG_IS_DETERMINISTIC_ECDSA ( 1u << 14 ) #define ALG_IS_RANDOMIZED_ECDSA ( 1u << 15 ) #define ALG_IS_HASH_EDDSA ( 1u << 16 ) -#define ALG_IS_SIGN_HASH ( 1u << 17 ) -#define ALG_IS_RSA_OAEP ( 1u << 18 ) -#define ALG_IS_HKDF ( 1u << 19 ) -#define ALG_IS_FFDH ( 1u << 20 ) -#define ALG_IS_ECDH ( 1u << 21 ) -#define ALG_IS_WILDCARD ( 1u << 22 ) -#define ALG_IS_RAW_KEY_AGREEMENT ( 1u << 23 ) -#define ALG_IS_AEAD_ON_BLOCK_CIPHER ( 1u << 24 ) -#define ALG_IS_TLS12_PRF ( 1u << 25 ) -#define ALG_IS_TLS12_PSK_TO_MS ( 1u << 26 ) +#define ALG_IS_SIGN_HASH ( 1u << 17 ) +#define ALG_IS_HASH_AND_SIGN ( 1u << 18 ) +#define ALG_IS_RSA_OAEP ( 1u << 19 ) +#define ALG_IS_HKDF ( 1u << 20 ) +#define ALG_IS_FFDH ( 1u << 21 ) +#define ALG_IS_ECDH ( 1u << 22 ) +#define ALG_IS_WILDCARD ( 1u << 23 ) +#define ALG_IS_RAW_KEY_AGREEMENT ( 1u << 24 ) +#define ALG_IS_AEAD_ON_BLOCK_CIPHER ( 1u << 25 ) +#define ALG_IS_TLS12_PRF ( 1u << 26 ) +#define ALG_IS_TLS12_PSK_TO_MS ( 1u << 27 ) /* Flags for key type classification macros. There is a flag for every * key type classification macro PSA_KEY_TYPE_IS_xxx except for some that @@ -51,7 +52,7 @@ #define KEY_TYPE_IS_VENDOR_DEFINED ( 1u << 0 ) #define KEY_TYPE_IS_UNSTRUCTURED ( 1u << 1 ) #define KEY_TYPE_IS_PUBLIC_KEY ( 1u << 2 ) -#define KEY_TYPE_IS_KEY_PAIR ( 1u << 3 ) +#define KEY_TYPE_IS_KEY_PAIR ( 1u << 3 ) #define KEY_TYPE_IS_RSA ( 1u << 4 ) #define KEY_TYPE_IS_DSA ( 1u << 5 ) #define KEY_TYPE_IS_ECC ( 1u << 6 ) @@ -115,6 +116,7 @@ void algorithm_classification( psa_algorithm_t alg, unsigned flags ) TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_ECDSA, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_EDDSA, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_SIGN_HASH, alg, flags ); + TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_AND_SIGN, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_OAEP, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_HKDF, alg, flags ); TEST_CLASSIFICATION_MACRO( ALG_IS_WILDCARD, alg, flags ); @@ -490,7 +492,9 @@ void asymmetric_signature_algorithm( int alg_arg, int classification_flags ) /* BEGIN_CASE */ void asymmetric_signature_wildcard( int alg_arg, int classification_flags ) { - classification_flags |= ALG_IS_SIGN_HASH | ALG_IS_WILDCARD; + classification_flags |= ALG_IS_WILDCARD; + classification_flags |= ALG_IS_SIGN_HASH; + classification_flags |= ALG_IS_HASH_AND_SIGN; test_asymmetric_signature_algorithm( alg_arg, classification_flags ); /* Any failure of this test function comes from * asymmetric_signature_algorithm. Pacify -Werror=unused-label. */ From c323d4585fd51b7c75c959c2289d6ab9efa14183 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 15 Oct 2021 21:38:35 +0200 Subject: [PATCH 11/13] Note the change to PSA_ALG_IS_HASH_AND_SIGN in the changelog Signed-off-by: Gilles Peskine --- ChangeLog.d/psa_crypto_api_macros.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog.d/psa_crypto_api_macros.txt b/ChangeLog.d/psa_crypto_api_macros.txt index c695ff5c95..ff53e33c2d 100644 --- a/ChangeLog.d/psa_crypto_api_macros.txt +++ b/ChangeLog.d/psa_crypto_api_macros.txt @@ -1,3 +1,11 @@ Features * Add missing PSA macros declared by PSA Crypto API 1.0.0: - PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL + PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL. + +Bugfix + * The existing predicate macro name PSA_ALG_IS_HASH_AND_SIGN is now reserved + for algorithm values that fully encode the hashing step, as per the PSA + Crypto API specification. This excludes PSA_ALG_RSA_PKCS1V15_SIGN_RAW and + PSA_ALG_ECDSA_ANY. The new predicate macro PSA_ALG_IS_SIGN_HASH covers + all algorithms that can be used with psa_{sign,verify}_hash(), including + these two. From a4256c1b2dc90fd144c154b746ff9d718bd33f35 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Nov 2021 14:18:08 +0100 Subject: [PATCH 12/13] Ensure that all flags are actually tested At least twice, we added a classification flag but forgot to test it in the relevant test functions. Add some protection so that this doesn't happen again. In each classification category, put a macro xxx_FLAG_MASK_PLUS_ONE at the end. In the corresponding test function, keep track of the flags that are tested, and check that their mask is xxx_FLAG_MASK_PLUS_ONE - 1 which is all the bits of the previous flags set. Now, if we add a flag without testing it, the test TEST_EQUAL( classification_flags_tested, xxx_FLAG_MASK_PLUS_ONE - 1 ) will fail. It will also fail if we make the set of flag numbers non-consecutive, which is ok. This reveals that three algorithm flags had been added but not tested (in two separate occasions). Also, one key type flag that is no longer used by the library was still defined but not tested, which is not a test gap but is inconsistent. It's for DSA, which is relevant to the PSA encoding even if Mbed TLS doesn't implement it, so keep the flag and do test it. Signed-off-by: Gilles Peskine --- .../test_suite_psa_crypto_metadata.function | 112 +++++++++++------- 1 file changed, 69 insertions(+), 43 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index 0f2fcec590..f02adf3a74 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -44,6 +44,7 @@ #define ALG_IS_AEAD_ON_BLOCK_CIPHER ( 1u << 25 ) #define ALG_IS_TLS12_PRF ( 1u << 26 ) #define ALG_IS_TLS12_PSK_TO_MS ( 1u << 27 ) +#define ALG_FLAG_MASK_PLUS_ONE ( 1u << 28 ) /* must be last! */ /* Flags for key type classification macros. There is a flag for every * key type classification macro PSA_KEY_TYPE_IS_xxx except for some that @@ -57,21 +58,38 @@ #define KEY_TYPE_IS_DSA ( 1u << 5 ) #define KEY_TYPE_IS_ECC ( 1u << 6 ) #define KEY_TYPE_IS_DH ( 1u << 7 ) +#define KEY_TYPE_FLAG_MASK_PLUS_ONE ( 1u << 8 ) /* must be last! */ /* Flags for lifetime classification macros. There is a flag for every * lifetime classification macro PSA_KEY_LIFETIME_IS_xxx. The name of the * flag is the name of the classification macro without the PSA_ prefix. */ #define KEY_LIFETIME_IS_VOLATILE ( 1u << 0 ) #define KEY_LIFETIME_IS_READ_ONLY ( 1u << 1 ) +#define KEY_LIFETIME_FLAG_MASK_PLUS_ONE ( 1u << 2 ) /* must be last! */ -#define TEST_CLASSIFICATION_MACRO( flag, alg, flags ) \ - do \ - { \ - if( ( flags ) & ( flag ) ) \ - TEST_ASSERT( PSA_##flag( alg ) ); \ - else \ - TEST_ASSERT( ! PSA_##flag( alg ) ); \ - } \ +/* Check that in the value of flags, the bit flag (which should be a macro + * expanding to a number of the form 1 << k) is set if and only if + * PSA_##flag(alg) is true. + * + * Only perform this check if cond is true. Typically cond is 1, but it can + * be different if the value of the flag bit is only specified under specific + * conditions. + * + * Unconditionally mask flag into the ambient variable + * classification_flags_tested. + */ +#define TEST_CLASSIFICATION_MACRO( cond, flag, alg, flags ) \ + do \ + { \ + if( cond ) \ + { \ + if( ( flags ) & ( flag ) ) \ + TEST_ASSERT( PSA_##flag( alg ) ); \ + else \ + TEST_ASSERT( ! PSA_##flag( alg ) ); \ + } \ + classification_flags_tested |= ( flag ); \ + } \ while( 0 ) /* Check the parity of value. @@ -98,45 +116,50 @@ int has_even_parity( uint32_t value ) void algorithm_classification( psa_algorithm_t alg, unsigned flags ) { - TEST_CLASSIFICATION_MACRO( ALG_IS_VENDOR_DEFINED, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_HMAC, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_BLOCK_CIPHER_MAC, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_STREAM_CIPHER, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_PKCS1V15_SIGN, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_PSS, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_DSA, alg, flags ); - if ( PSA_ALG_IS_DSA( alg ) ) - TEST_CLASSIFICATION_MACRO( ALG_DSA_IS_DETERMINISTIC, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_DETERMINISTIC_DSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_DSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_ECDSA, alg, flags ); - if ( PSA_ALG_IS_ECDSA( alg ) ) - TEST_CLASSIFICATION_MACRO( ALG_ECDSA_IS_DETERMINISTIC, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_DETERMINISTIC_ECDSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_ECDSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_EDDSA, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_SIGN_HASH, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_AND_SIGN, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_OAEP, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_HKDF, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_WILDCARD, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_ECDH, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_FFDH, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_RAW_KEY_AGREEMENT, alg, flags ); - TEST_CLASSIFICATION_MACRO( ALG_IS_AEAD_ON_BLOCK_CIPHER, alg, flags ); + unsigned classification_flags_tested = 0; + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_VENDOR_DEFINED, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HMAC, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_BLOCK_CIPHER_MAC, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_STREAM_CIPHER, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PKCS1V15_SIGN, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( PSA_ALG_IS_DSA( alg ), + ALG_DSA_IS_DETERMINISTIC, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DETERMINISTIC_DSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RANDOMIZED_DSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_ECDSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( PSA_ALG_IS_ECDSA( alg ), + ALG_ECDSA_IS_DETERMINISTIC, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DETERMINISTIC_ECDSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RANDOMIZED_ECDSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HASH_EDDSA, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_SIGN_HASH, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HASH_AND_SIGN, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_OAEP, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HKDF, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_WILDCARD, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_ECDH, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_FFDH, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RAW_KEY_AGREEMENT, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_AEAD_ON_BLOCK_CIPHER, alg, flags ); + TEST_EQUAL( classification_flags_tested, ALG_FLAG_MASK_PLUS_ONE - 1 ); exit: ; } void key_type_classification( psa_key_type_t type, unsigned flags ) { + unsigned classification_flags_tested = 0; + /* Macros tested based on the test case parameter */ - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_VENDOR_DEFINED, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_UNSTRUCTURED, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_PUBLIC_KEY, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_KEY_PAIR, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_RSA, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_ECC, type, flags ); - TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_DH, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_VENDOR_DEFINED, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_UNSTRUCTURED, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_PUBLIC_KEY, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_KEY_PAIR, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_RSA, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_ECC, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_DH, type, flags ); + TEST_EQUAL( classification_flags_tested, KEY_TYPE_FLAG_MASK_PLUS_ONE - 1 ); /* Macros with derived semantics */ TEST_EQUAL( PSA_KEY_TYPE_IS_ASYMMETRIC( type ), @@ -698,9 +721,12 @@ void lifetime( int lifetime_arg, int classification_flags, psa_key_persistence_t persistence = persistence_arg; psa_key_location_t location = location_arg; unsigned flags = classification_flags; + unsigned classification_flags_tested = 0; - TEST_CLASSIFICATION_MACRO( KEY_LIFETIME_IS_VOLATILE, lifetime, flags ); - TEST_CLASSIFICATION_MACRO( KEY_LIFETIME_IS_READ_ONLY, lifetime, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_LIFETIME_IS_VOLATILE, lifetime, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_LIFETIME_IS_READ_ONLY, lifetime, flags ); + TEST_EQUAL( classification_flags_tested, + KEY_LIFETIME_FLAG_MASK_PLUS_ONE - 1 ); TEST_EQUAL( PSA_KEY_LIFETIME_GET_PERSISTENCE( lifetime ), persistence ); TEST_EQUAL( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ), location ); From 4db2624bfe2bd47b87be2d53747db8d59c1dc58f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Nov 2021 13:56:47 +0100 Subject: [PATCH 13/13] Fix test bug: some classification flags were not tested Signed-off-by: Gilles Peskine --- tests/suites/test_suite_psa_crypto_metadata.function | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index f02adf3a74..092780c4db 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -123,6 +123,8 @@ void algorithm_classification( psa_algorithm_t alg, unsigned flags ) TEST_CLASSIFICATION_MACRO( 1, ALG_IS_STREAM_CIPHER, alg, flags ); TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PKCS1V15_SIGN, alg, flags ); TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS_ANY_SALT, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS_STANDARD_SALT, alg, flags ); TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DSA, alg, flags ); TEST_CLASSIFICATION_MACRO( PSA_ALG_IS_DSA( alg ), ALG_DSA_IS_DETERMINISTIC, alg, flags ); @@ -143,6 +145,8 @@ void algorithm_classification( psa_algorithm_t alg, unsigned flags ) TEST_CLASSIFICATION_MACRO( 1, ALG_IS_FFDH, alg, flags ); TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RAW_KEY_AGREEMENT, alg, flags ); TEST_CLASSIFICATION_MACRO( 1, ALG_IS_AEAD_ON_BLOCK_CIPHER, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_TLS12_PRF, alg, flags ); + TEST_CLASSIFICATION_MACRO( 1, ALG_IS_TLS12_PSK_TO_MS, alg, flags ); TEST_EQUAL( classification_flags_tested, ALG_FLAG_MASK_PLUS_ONE - 1 ); exit: ; } @@ -157,6 +161,7 @@ void key_type_classification( psa_key_type_t type, unsigned flags ) TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_PUBLIC_KEY, type, flags ); TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_KEY_PAIR, type, flags ); TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_RSA, type, flags ); + TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_DSA, type, flags ); TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_ECC, type, flags ); TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_DH, type, flags ); TEST_EQUAL( classification_flags_tested, KEY_TYPE_FLAG_MASK_PLUS_ONE - 1 );