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 <Gilles.Peskine@arm.com>
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 524e2dc..a29beb5 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -1545,7 +1545,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).
*
@@ -1554,9 +1567,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().
@@ -1570,11 +1582,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
@@ -1584,8 +1602,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.
*
@@ -1607,7 +1626,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)