diff --git a/ChangeLog.d/psa_crypto_api_macros.txt b/ChangeLog.d/psa_crypto_api_macros.txt new file mode 100644 index 000000000..ff53e33c2 --- /dev/null +++ b/ChangeLog.d/psa_crypto_api_macros.txt @@ -0,0 +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. + +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. diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 5d9854a7b..ee4b54cbf 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_sizes.h b/include/psa/crypto_sizes.h index 4c67f10af..5f230e0f0 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. diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 621b872fc..f0d76fb55 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) @@ -1589,20 +1592,24 @@ * file. */ #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 -/** Whether the specified algorithm is a hash-and-sign algorithm. +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_hash() and psa_verify_hash(). * - * 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. + * 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). + * \param alg An algorithm identifier (value of type psa_algorithm_t). * - * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. + * \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_HASH_AND_SIGN(alg) \ +#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)) @@ -1619,7 +1626,37 @@ * 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 hash-and-sign algorithm. + * + * 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-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). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) && \ + ((alg) & PSA_ALG_HASH_MASK) != 0) /** Get the hash used by a hash-and-sign signature algorithm. * @@ -1641,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) @@ -2132,6 +2168,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) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3670071a5..c4bcddcb1 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 ); @@ -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 ); } @@ -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/library/psa_crypto_mac.c b/library/psa_crypto_mac.c index 2c079d434..7e0a8325d 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 ); diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c index 923d2c136..91bac678e 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 591c2960d..01a06989d 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 ad806c77c..83763c55d 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 | 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_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 | 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_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 | ALG_IS_HASH_AND_SIGN 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 | 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_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 | 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_HASH_AND_SIGN +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_HASH_AND_SIGN +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 ab9b2f879..092780c4d 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -33,16 +33,18 @@ #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_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 ) +#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 @@ -51,26 +53,43 @@ #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 ) #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. @@ -97,44 +116,55 @@ 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_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_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 ); + 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_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: ; } 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_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 ); /* Macros with derived semantics */ TEST_EQUAL( PSA_KEY_TYPE_IS_ASYMMETRIC( type ), @@ -353,6 +383,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, @@ -489,7 +520,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_HASH_AND_SIGN | 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. */ @@ -693,9 +726,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 );