Add support for minimum-tag-length AEAD and MAC policies
Includes tests.
Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
# Conflicts:
# include/psa/crypto_values.h
# tests/suites/test_suite_psa_crypto.function
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 271fb99..a8fe59a 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -264,6 +264,12 @@
* - An algorithm value permits this particular algorithm.
* - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified
* signature scheme with any hash algorithm.
+ * - An algorithm value for which PSA_ALG_IS_WILDCARD() evaluates to true
+ * allows any algorithm specified by that usage algorithm definition.
+ * E.g. a usage algorithm built from PSA_ALG_MAC_WITH_MINIMUM_LENGTH_TAG()
+ * allows using the key for any algorithm with the same base MAC algorithm as
+ * long as the used algorithm isn't truncated to less than the minimum tag
+ * length declared in the usage algorithm.
*
* This function overwrites any algorithm policy
* previously set in \p attributes.
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 7002631..368581c 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -900,7 +900,7 @@
* too large for the specified MAC algorithm.
*/
#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \
- (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \
+ (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | PSA_ALG_MAC_MINIMUM_LENGTH_FLAG)) | \
((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK))
/** Macro to build the base MAC algorithm corresponding to a truncated
@@ -916,7 +916,7 @@
* MAC algorithm.
*/
#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \
- ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK)
+ ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | PSA_ALG_MAC_MINIMUM_LENGTH_FLAG))
/** Length to which a MAC algorithm is truncated.
*
@@ -932,6 +932,34 @@
#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \
(((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET)
+/* In the encoding of a MAC algorithm, the bit corresponding to
+ * PSA_ALG_MAC_MINIMUM_LENGTH_FLAG encodes the fact that the algorithm is
+ * a usage algorithm, which allows any algorithm corresponding to the same
+ * base class and a tag length greater or equal than the one encoded in
+ * PSA_ALG_MAC_TRUNCATION_MASK. */
+#define PSA_ALG_MAC_MINIMUM_LENGTH_FLAG ((psa_algorithm_t)0x00008000)
+
+/** Macro to build a MAC minimum-tag-length usage algorithm.
+ *
+ * A mininimum-tag-length MAC usage algorithm contains all MAC algorithms
+ * sharing the same base algorithm, and where the tag length of the specific
+ * algorithm is equal to or larger then the usage's minimum tag length.
+ *
+ * \param mac_alg A MAC algorithm identifier (value of type
+ * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg)
+ * is true).
+ * \param tag_length Desired minimum length of the authentication tag in
+ * bytes.
+ *
+ * \return The corresponding MAC usage algorithm with the
+ * specified minimum length.
+ * \return Unspecified if \p alg is not a supported
+ * MAC algorithm or if \p tag_length is not valid
+ * for the specified MAC algorithm.
+ */
+#define PSA_ALG_MAC_WITH_MINIMUM_LENGTH_TAG(mac_alg, tag_length) \
+ ( PSA_ALG_TRUNCATED_MAC(mac_alg, tag_length) | PSA_ALG_MAC_MINIMUM_LENGTH_FLAG )
+
#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x03c00000)
/** The CBC-MAC construction over a block cipher
*
@@ -1111,10 +1139,25 @@
* for the specified AEAD algorithm.
*/
#define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \
- (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \
+ (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_MINIMUM_LENGTH_FLAG)) | \
((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \
PSA_ALG_AEAD_TAG_LENGTH_MASK))
+/** Retrieve the tag length of a specified AEAD algorithm
+ *
+ * \param aead_alg An AEAD algorithm identifier (value of type
+ * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg)
+ * is true).
+ *
+ * \return The tag length specified by the input algorithm.
+ * \return Unspecified if \p alg is not a supported
+ * AEAD algorithm or if \p tag_length is not valid
+ * for the specified AEAD algorithm.
+ */
+#define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg) \
+ (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> \
+ PSA_AEAD_TAG_LENGTH_OFFSET )
+
/** Calculate the corresponding AEAD algorithm with the default tag length.
*
* \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that
@@ -1134,6 +1177,34 @@
PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ? \
ref :
+/* In the encoding of an AEAD algorithm, the bit corresponding to
+ * PSA_ALG_AEAD_MINIMUM_LENGTH_FLAG encodes the fact that the algorithm is
+ * a usage algorithm, which allows any algorithm corresponding to the same
+ * base class and a tag length greater or equal than the one encoded in
+ * PSA_ALG_AEAD_TAG_LENGTH_MASK. */
+#define PSA_ALG_AEAD_MINIMUM_LENGTH_FLAG ((psa_algorithm_t)0x00008000)
+
+/** Macro to build an AEAD minimum-tag-length usage algorithm.
+ *
+ * A mininimum-tag-length AEAD usage algorithm contains all AEAD algorithms
+ * sharing the same base algorithm, and where the tag length of the specific
+ * algorithm is equal to or larger then the usage's minimum tag length.
+ *
+ * \param aead_alg An AEAD algorithm identifier (value of type
+ * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg)
+ * is true).
+ * \param tag_length Desired minimum length of the authentication tag in
+ * bytes.
+ *
+ * \return The corresponding AEAD usage algorithm with the
+ * specified minimum length.
+ * \return Unspecified if \p alg is not a supported
+ * AEAD algorithm or if \p tag_length is not valid
+ * for the specified AEAD algorithm.
+ */
+#define PSA_ALG_AEAD_WITH_MINIMUM_LENGTH_TAG(aead_alg, tag_length) \
+ ( PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) | PSA_ALG_AEAD_MINIMUM_LENGTH_FLAG )
+
#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x06000200)
/** RSA PKCS#1 v1.5 signature with hashing.
*
@@ -1580,10 +1651,14 @@
* \return This macro may return either 0 or 1 if \c alg is not a supported
* algorithm identifier.
*/
-#define PSA_ALG_IS_WILDCARD(alg) \
- (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \
- PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \
- (alg) == PSA_ALG_ANY_HASH)
+#define PSA_ALG_IS_WILDCARD(alg) \
+ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \
+ PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \
+ (PSA_ALG_IS_MAC(alg) ? \
+ (alg & PSA_ALG_MAC_MINIMUM_LENGTH_FLAG) != 0 : \
+ (PSA_ALG_IS_AEAD(alg) ? \
+ (alg & PSA_ALG_AEAD_MINIMUM_LENGTH_FLAG) != 0 : \
+ (alg) == PSA_ALG_ANY_HASH)))
/**@}*/