Skip to content

Commit acec0cc

Browse files
Add a hash wildcard value for hash-and-sign algorithm
You can use PSA_ALG_ANY_HASH to build the algorithm value for a hash-and-sign algorithm in a policy. Then the policy allows usage with this hash-and-sign family with any hash. Test that PSA_ALG_ANY_HASH-based policies allow a specific hash, but not a different hash-and-sign family. Test that PSA_ALG_ANY_HASH is not valid for operations, only in policies.
1 parent d35b489 commit acec0cc

File tree

6 files changed

+179
-16
lines changed

6 files changed

+179
-16
lines changed

include/psa/crypto_values.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@
641641
(((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION)
642642

643643
#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff)
644+
644645
#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001)
645646
#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002)
646647
#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003)
@@ -667,6 +668,40 @@
667668
/** SHA3-512 */
668669
#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013)
669670

671+
/** Allow any hash algorithm.
672+
*
673+
* This value may only be used to form the algorithm usage field of a policy
674+
* for a signature algorithm that is parametrized by a hash. That is,
675+
* suppose that `PSA_xxx_SIGN` is one of the following macros:
676+
* - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS,
677+
* - #PSA_ALG_DSA, #PSA_ALG_DETERMINISTIC_DSA,
678+
* - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA.
679+
* Then you may create a key as follows:
680+
* - Set the key usage field using #PSA_ALG_ANY_HASH, for example:
681+
* ```
682+
* psa_key_policy_set_usage(&policy,
683+
* PSA_KEY_USAGE_SIGN, //or PSA_KEY_USAGE_VERIFY
684+
* PSA_xxx_SIGN(PSA_ALG_ANY_HASH));
685+
* psa_set_key_policy(handle, &policy);
686+
* ```
687+
* - Import or generate key material.
688+
* - Call psa_asymmetric_sign() or psa_asymmetric_verify(), passing
689+
* an algorithm built from `PSA_xxx_SIGN` and a specific hash. Each
690+
* call to sign or verify a message may use a different hash.
691+
* ```
692+
* psa_asymmetric_sign(handle, PSA_xxx_SIGN(PSA_ALG_SHA_256), ...);
693+
* psa_asymmetric_sign(handle, PSA_xxx_SIGN(PSA_ALG_SHA_512), ...);
694+
* psa_asymmetric_sign(handle, PSA_xxx_SIGN(PSA_ALG_SHA3_256), ...);
695+
* ```
696+
*
697+
* This value may not be used to build other algorithms that are
698+
* parametrized over a hash.
699+
*
700+
* This value may not be used to build an algorithm specification to
701+
* perform an operation. It is only valid to build policies.
702+
*/
703+
#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff)
704+
670705
#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000)
671706
#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000)
672707
/** Macro to build an HMAC algorithm.
@@ -914,6 +949,8 @@
914949
*
915950
* \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
916951
* #PSA_ALG_IS_HASH(\p hash_alg) is true).
952+
* This includes #PSA_ALG_ANY_HASH
953+
* when specifying the algorithm in a usage policy.
917954
*
918955
* \return The corresponding RSA PKCS#1 v1.5 signature algorithm.
919956
* \return Unspecified if \p alg is not a supported
@@ -943,6 +980,8 @@
943980
*
944981
* \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
945982
* #PSA_ALG_IS_HASH(\p hash_alg) is true).
983+
* This includes #PSA_ALG_ANY_HASH
984+
* when specifying the algorithm in a usage policy.
946985
*
947986
* \return The corresponding RSA PSS signature algorithm.
948987
* \return Unspecified if \p alg is not a supported
@@ -961,6 +1000,8 @@
9611000
*
9621001
* \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
9631002
* #PSA_ALG_IS_HASH(\p hash_alg) is true).
1003+
* This includes #PSA_ALG_ANY_HASH
1004+
* when specifying the algorithm in a usage policy.
9641005
*
9651006
* \return The corresponding DSA signature algorithm.
9661007
* \return Unspecified if \p alg is not a supported
@@ -996,6 +1037,8 @@
9961037
*
9971038
* \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
9981039
* #PSA_ALG_IS_HASH(\p hash_alg) is true).
1040+
* This includes #PSA_ALG_ANY_HASH
1041+
* when specifying the algorithm in a usage policy.
9991042
*
10001043
* \return The corresponding ECDSA signature algorithm.
10011044
* \return Unspecified if \p alg is not a supported
@@ -1028,6 +1071,8 @@
10281071
*
10291072
* \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that
10301073
* #PSA_ALG_IS_HASH(\p hash_alg) is true).
1074+
* This includes #PSA_ALG_ANY_HASH
1075+
* when specifying the algorithm in a usage policy.
10311076
*
10321077
* \return The corresponding deterministic ECDSA signature
10331078
* algorithm.
@@ -1341,6 +1386,24 @@
13411386
#define PSA_ALG_IS_ECDH(alg) \
13421387
(PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH_BASE)
13431388

1389+
/** Whether the specified algorithm encoding is a wildcard.
1390+
*
1391+
* Wildcard values may only be used to set the usage algorithm field in
1392+
* a policy, not to perform an operation.
1393+
*
1394+
* \param alg An algorithm identifier (value of type #psa_algorithm_t).
1395+
*
1396+
* \return 1 if \c alg is a wildcard algorithm encoding.
1397+
* \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for
1398+
* an operation).
1399+
* \return This macro may return either 0 or 1 if \c alg is not a supported
1400+
* algorithm identifier.
1401+
*/
1402+
#define PSA_ALG_IS_WILDCARD(alg) \
1403+
(PSA_ALG_IS_HASH_AND_SIGN(alg) ? \
1404+
PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \
1405+
(alg) == PSA_ALG_ANY_HASH)
1406+
13441407
/**@}*/
13451408

13461409
/** \defgroup key_lifetimes Key lifetimes

library/psa_crypto.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,29 @@ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle,
713713
return( status );
714714
}
715715

716+
/** Test whether a policy permits an algorithm.
717+
*
718+
* The caller must test usage flags separately.
719+
*/
720+
static int psa_key_policy_permits( const psa_key_policy_t *policy,
721+
psa_algorithm_t alg )
722+
{
723+
/* Common case: the policy only allows alg. */
724+
if( alg == policy->alg )
725+
return( 1 );
726+
/* If policy->alg is a hash-and-sign with a wildcard for the hash,
727+
* and alg is the same hash-and-sign family with any hash,
728+
* then alg is compliant with policy->alg. */
729+
if( PSA_ALG_IS_HASH_AND_SIGN( alg ) &&
730+
PSA_ALG_SIGN_GET_HASH( policy->alg ) == PSA_ALG_ANY_HASH )
731+
{
732+
return( ( policy->alg & ~PSA_ALG_HASH_MASK ) ==
733+
( alg & ~PSA_ALG_HASH_MASK ) );
734+
}
735+
/* If it isn't permitted, it's forbidden. */
736+
return( 0 );
737+
}
738+
716739
/** Retrieve a slot which must contain a key. The key must have allow all the
717740
* usage flags set in \p usage. If \p alg is nonzero, the key must allow
718741
* operations with this algorithm. */
@@ -740,7 +763,9 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
740763
usage &= ~PSA_KEY_USAGE_EXPORT;
741764
if( ( slot->policy.usage & usage ) != usage )
742765
return( PSA_ERROR_NOT_PERMITTED );
743-
if( alg != 0 && ( alg != slot->policy.alg ) )
766+
767+
/* Enforce that the usage policy permits the requested algortihm. */
768+
if( alg != 0 && ! psa_key_policy_permits( &slot->policy, alg ) )
744769
return( PSA_ERROR_NOT_PERMITTED );
745770

746771
*p_slot = slot;

0 commit comments

Comments
 (0)