blob: b51f2a28b783714ea5cf462ef62c5bbc03d74d0f [file] [log] [blame]
/* BEGIN_HEADER */
/* Test macros that provide metadata about algorithms and key types.
* This test suite only contains tests that don't require executing
* code. Other test suites validate macros that require creating a key
* and using it. */
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
#include "spm/psa_defs.h"
#endif
#include "psa/crypto.h"
#include "psa_crypto_invasive.h"
/* Flags for algorithm classification macros. There is a flag for every
* algorithm classification macro PSA_ALG_IS_xxx except for the
* category test macros, which are hard-coded in each
* category-specific function. The name of the flag is the name of the
* classification macro without the PSA_ prefix. */
#define ALG_IS_VENDOR_DEFINED (1u << 0)
#define ALG_IS_HMAC (1u << 1)
#define ALG_IS_BLOCK_CIPHER_MAC (1u << 2)
#define ALG_IS_STREAM_CIPHER (1u << 3)
#define ALG_IS_RSA_PKCS1V15_SIGN (1u << 4)
#define ALG_IS_RSA_PSS (1u << 5)
#define ALG_IS_RSA_PSS_ANY_SALT (1u << 6)
#define ALG_IS_RSA_PSS_STANDARD_SALT (1u << 7)
#define ALG_IS_DSA (1u << 8)
#define ALG_DSA_IS_DETERMINISTIC (1u << 9)
#define ALG_IS_DETERMINISTIC_DSA (1u << 10)
#define ALG_IS_RANDOMIZED_DSA (1u << 11)
#define ALG_IS_ECDSA (1u << 12)
#define ALG_ECDSA_IS_DETERMINISTIC (1u << 13)
#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_HASH_AND_SIGN (1u << 18)
#define ALG_IS_RSA_OAEP (1u << 19)
#define ALG_IS_HKDF (1u << 20)
#define ALG_IS_HKDF_EXTRACT (1u << 21)
#define ALG_IS_HKDF_EXPAND (1u << 22)
#define ALG_IS_FFDH (1u << 23)
#define ALG_IS_ECDH (1u << 24)
#define ALG_IS_WILDCARD (1u << 25)
#define ALG_IS_RAW_KEY_AGREEMENT (1u << 26)
#define ALG_IS_AEAD_ON_BLOCK_CIPHER (1u << 27)
#define ALG_IS_TLS12_PRF (1u << 28)
#define ALG_IS_TLS12_PSK_TO_MS (1u << 29)
#define ALG_FLAG_MASK_PLUS_ONE (1u << 30) /* 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
* are tested as derived from other macros. The name of the flag is
* the name of the classification macro without the PSA_ prefix. */
#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_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! */
/* 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.
*
* There are several numerical encodings for which the PSA Cryptography API
* specification deliberately defines encodings that all have the same
* parity. This way, a data glitch that flips one bit in the data cannot
* possibly turn a valid encoding into another valid encoding. Here in
* the tests, we check that the values (including Mbed TLS vendor-specific
* values) have the expected parity.
*
* The expected parity is even so that 0 is considered a valid encoding.
*
* Return a nonzero value if value has even parity and 0 otherwise. */
int has_even_parity(uint32_t value)
{
value ^= value >> 16;
value ^= value >> 8;
value ^= value >> 4;
return 0x9669 & 1 << (value & 0xf);
}
#define TEST_PARITY(value) \
TEST_ASSERT(has_even_parity(value))
void algorithm_classification(psa_algorithm_t alg, unsigned 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_HKDF_EXTRACT, alg, flags);
TEST_CLASSIFICATION_MACRO(1, ALG_IS_HKDF_EXPAND, 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(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),
(PSA_KEY_TYPE_IS_PUBLIC_KEY(type) ||
PSA_KEY_TYPE_IS_KEY_PAIR(type)));
TEST_EQUAL(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type),
(PSA_KEY_TYPE_IS_ECC(type) &&
PSA_KEY_TYPE_IS_KEY_PAIR(type)));
TEST_EQUAL(PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type),
(PSA_KEY_TYPE_IS_ECC(type) &&
PSA_KEY_TYPE_IS_PUBLIC_KEY(type)));
TEST_EQUAL(PSA_KEY_TYPE_IS_DH_KEY_PAIR(type),
(PSA_KEY_TYPE_IS_DH(type) &&
PSA_KEY_TYPE_IS_KEY_PAIR(type)));
TEST_EQUAL(PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type),
(PSA_KEY_TYPE_IS_DH(type) &&
PSA_KEY_TYPE_IS_PUBLIC_KEY(type)));
TEST_PARITY(type);
exit:;
}
void mac_algorithm_core(psa_algorithm_t alg, int classification_flags,
psa_key_type_t key_type, size_t key_bits,
size_t length)
{
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
/* Length */
TEST_EQUAL(length, PSA_MAC_LENGTH(key_type, key_bits, alg));
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
PSA_ASSERT(psa_mac_key_can_do(alg, key_type));
#endif
exit:;
}
void aead_algorithm_core(psa_algorithm_t alg, int classification_flags,
psa_key_type_t key_type, size_t key_bits,
size_t tag_length)
{
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
/* Tag length */
TEST_EQUAL(tag_length, PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg));
exit:;
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_PSA_CRYPTO_CLIENT
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
void hash_algorithm(int alg_arg, int length_arg)
{
psa_algorithm_t alg = alg_arg;
size_t length = length_arg;
psa_algorithm_t hmac_alg = PSA_ALG_HMAC(alg);
psa_algorithm_t rsa_pkcs1v15_sign_alg = PSA_ALG_RSA_PKCS1V15_SIGN(alg);
psa_algorithm_t rsa_pss_alg = PSA_ALG_RSA_PSS(alg);
psa_algorithm_t dsa_alg = PSA_ALG_DSA(alg);
psa_algorithm_t deterministic_dsa_alg = PSA_ALG_DETERMINISTIC_DSA(alg);
psa_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(alg);
psa_algorithm_t deterministic_ecdsa_alg = PSA_ALG_DETERMINISTIC_ECDSA(alg);
psa_algorithm_t rsa_oaep_alg = PSA_ALG_RSA_OAEP(alg);
psa_algorithm_t hkdf_alg = PSA_ALG_HKDF(alg);
/* Algorithm classification */
TEST_ASSERT(PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, 0);
/* Dependent algorithms */
TEST_EQUAL(PSA_ALG_HMAC_GET_HASH(hmac_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(rsa_pkcs1v15_sign_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(rsa_pss_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(dsa_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(deterministic_dsa_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(ecdsa_alg), alg);
TEST_EQUAL(PSA_ALG_SIGN_GET_HASH(deterministic_ecdsa_alg), alg);
TEST_EQUAL(PSA_ALG_RSA_OAEP_GET_HASH(rsa_oaep_alg), alg);
TEST_EQUAL(PSA_ALG_HKDF_GET_HASH(hkdf_alg), alg);
/* Hash length */
TEST_EQUAL(length, PSA_HASH_LENGTH(alg));
TEST_ASSERT(length <= PSA_HASH_MAX_SIZE);
}
/* END_CASE */
/* BEGIN_CASE */
void mac_algorithm(int alg_arg, int classification_flags,
int length_arg,
int key_type_arg, int key_bits_arg)
{
psa_algorithm_t alg = alg_arg;
size_t length = length_arg;
size_t n;
size_t key_type = key_type_arg;
size_t key_bits = key_bits_arg;
mac_algorithm_core(alg, classification_flags,
key_type, key_bits, length);
TEST_EQUAL(PSA_ALG_FULL_LENGTH_MAC(alg), alg);
TEST_ASSERT(length <= PSA_MAC_MAX_SIZE);
/* Truncated versions */
for (n = 1; n <= length; n++) {
psa_algorithm_t truncated_alg = PSA_ALG_TRUNCATED_MAC(alg, n);
mac_algorithm_core(truncated_alg, classification_flags,
key_type, key_bits, n);
TEST_EQUAL(PSA_ALG_FULL_LENGTH_MAC(truncated_alg), alg);
/* Check that calling PSA_ALG_TRUNCATED_MAC twice gives the length
* of the outer truncation (even if the outer length is smaller than
* the inner length). */
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(truncated_alg, 1),
PSA_ALG_TRUNCATED_MAC(alg, 1));
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(truncated_alg, length - 1),
PSA_ALG_TRUNCATED_MAC(alg, length - 1));
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(truncated_alg, length),
PSA_ALG_TRUNCATED_MAC(alg, length));
/* Check that calling PSA_ALG_TRUNCATED_MAC on an algorithm
* earlier constructed with PSA_ALG_AT_LEAST_THIS_LENGTH_MAC gives the
* length of the outer truncation (even if the outer length is smaller
* than the inner length). */
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(truncated_alg, n), 1),
PSA_ALG_TRUNCATED_MAC(alg, 1));
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(truncated_alg, n), length - 1),
PSA_ALG_TRUNCATED_MAC(alg, length - 1));
TEST_EQUAL(PSA_ALG_TRUNCATED_MAC(
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(truncated_alg, n), length),
PSA_ALG_TRUNCATED_MAC(alg, length));
}
/* At-leat-this-length versions */
for (n = 1; n <= length; n++) {
psa_algorithm_t policy_alg = PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, n);
mac_algorithm_core(policy_alg, classification_flags | ALG_IS_WILDCARD,
key_type, key_bits, n);
TEST_EQUAL(PSA_ALG_FULL_LENGTH_MAC(policy_alg), alg);
/* Check that calling PSA_ALG_AT_LEAST_THIS_LENGTH_MAC twice gives the
* length of the outer truncation (even if the outer length is smaller
* than the inner length). */
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(policy_alg, 1),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, 1));
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(policy_alg, length - 1),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, length - 1));
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(policy_alg, length),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, length));
/* Check that calling PSA_ALG_AT_LEAST_THIS_LENGTH_MAC on an algorithm
* earlier constructed with PSA_ALG_TRUNCATED_MAC gives the length of
* the outer truncation (even if the outer length is smaller than the
* inner length). */
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
PSA_ALG_TRUNCATED_MAC(policy_alg, n), 1),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, 1));
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
PSA_ALG_TRUNCATED_MAC(policy_alg, n), length - 1),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, length - 1));
TEST_EQUAL(PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
PSA_ALG_TRUNCATED_MAC(policy_alg, n), length),
PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg, length));
}
}
/* END_CASE */
/* BEGIN_CASE */
void hmac_algorithm(int alg_arg,
int length_arg,
int block_size_arg)
{
psa_algorithm_t alg = alg_arg;
psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(alg);
size_t block_size = block_size_arg;
size_t length = length_arg;
size_t n;
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,
PSA_KEY_TYPE_HMAC, PSA_BYTES_TO_BITS(length));
for (n = 1; n <= length; n++) {
psa_algorithm_t truncated_alg = PSA_ALG_TRUNCATED_MAC(alg, n);
TEST_EQUAL(PSA_ALG_HMAC_GET_HASH(truncated_alg), hash_alg);
}
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_algorithm(int alg_arg, int classification_flags)
{
psa_algorithm_t alg = alg_arg;
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
}
/* END_CASE */
/* BEGIN_CASE */
void aead_algorithm(int alg_arg, int classification_flags,
int tag_length_arg,
int key_type_arg, int key_bits_arg)
{
psa_algorithm_t alg = alg_arg;
size_t tag_length = tag_length_arg;
size_t n;
psa_key_type_t key_type = key_type_arg;
size_t key_bits = key_bits_arg;
aead_algorithm_core(alg, classification_flags,
key_type, key_bits, tag_length);
/* Truncated versions */
for (n = 1; n <= tag_length; n++) {
psa_algorithm_t truncated_alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, n);
aead_algorithm_core(truncated_alg, classification_flags,
key_type, key_bits, n);
TEST_EQUAL(PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(truncated_alg),
alg);
/* Check that calling PSA_ALG_AEAD_WITH_SHORTENED_TAG twice gives
* the length of the outer truncation (even if the outer length is
* smaller than the inner length). */
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(truncated_alg, 1),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(truncated_alg, tag_length - 1),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, tag_length - 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(truncated_alg, tag_length),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, tag_length));
/* Check that calling PSA_ALG_AEAD_WITH_SHORTENED_TAG on an algorithm
* earlier constructed with PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG
* gives the length of the outer truncation (even if the outer length is
* smaller than the inner length). */
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(truncated_alg, n), 1),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(truncated_alg,
n), tag_length - 1),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, tag_length - 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_SHORTENED_TAG(
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(truncated_alg, n), tag_length),
PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, tag_length));
}
/* At-leat-this-length versions */
for (n = 1; n <= tag_length; n++) {
psa_algorithm_t policy_alg = PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, n);
aead_algorithm_core(policy_alg, classification_flags | ALG_IS_WILDCARD,
key_type, key_bits, n);
TEST_EQUAL(PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(policy_alg),
alg);
/* Check that calling PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG twice
* gives the length of the outer truncation (even if the outer length is
* smaller than the inner length). */
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(policy_alg, 1),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(policy_alg, tag_length - 1),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, tag_length - 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(policy_alg, tag_length),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, tag_length));
/* Check that calling PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG on an
* algorithm earlier constructed with PSA_ALG_AEAD_WITH_SHORTENED_TAG
* gives the length of the outer truncation (even if the outer length is
* smaller than the inner length). */
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, n), 1),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, n), tag_length - 1),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, tag_length - 1));
TEST_EQUAL(PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, n), tag_length),
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(alg, tag_length));
}
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_signature_algorithm(int alg_arg, int classification_flags)
{
psa_algorithm_t alg = alg_arg;
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_signature_wildcard(int alg_arg, int classification_flags)
{
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. */
goto exit;
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_encryption_algorithm(int alg_arg, int classification_flags)
{
psa_algorithm_t alg = alg_arg;
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
}
/* END_CASE */
/* BEGIN_CASE */
void key_derivation_algorithm(int alg_arg, int classification_flags)
{
psa_algorithm_t alg = alg_arg;
psa_algorithm_t ecdh_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, alg);
psa_algorithm_t ffdh_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, alg);
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
/* Check combinations with key agreements */
TEST_ASSERT(PSA_ALG_IS_KEY_AGREEMENT(ecdh_alg));
TEST_ASSERT(PSA_ALG_IS_KEY_AGREEMENT(ffdh_alg));
TEST_EQUAL(PSA_ALG_KEY_AGREEMENT_GET_KDF(ecdh_alg), alg);
TEST_EQUAL(PSA_ALG_KEY_AGREEMENT_GET_KDF(ffdh_alg), alg);
}
/* END_CASE */
/* BEGIN_CASE */
void key_agreement_algorithm(int alg_arg, int classification_flags,
int ka_alg_arg, int kdf_alg_arg)
{
psa_algorithm_t alg = alg_arg;
psa_algorithm_t actual_ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg);
psa_algorithm_t expected_ka_alg = ka_alg_arg;
psa_algorithm_t actual_kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
psa_algorithm_t expected_kdf_alg = kdf_alg_arg;
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(!PSA_ALG_IS_PAKE(alg));
algorithm_classification(alg, classification_flags);
/* Shared secret derivation properties */
TEST_EQUAL(actual_ka_alg, expected_ka_alg);
TEST_EQUAL(actual_kdf_alg, expected_kdf_alg);
}
/* END_CASE */
/* BEGIN_CASE */
void pake_algorithm(int alg_arg)
{
psa_algorithm_t alg = alg_arg;
/* Algorithm classification */
TEST_ASSERT(!PSA_ALG_IS_HASH(alg));
TEST_ASSERT(!PSA_ALG_IS_MAC(alg));
TEST_ASSERT(!PSA_ALG_IS_CIPHER(alg));
TEST_ASSERT(!PSA_ALG_IS_AEAD(alg));
TEST_ASSERT(!PSA_ALG_IS_SIGN(alg));
TEST_ASSERT(!PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_AGREEMENT(alg));
TEST_ASSERT(!PSA_ALG_IS_KEY_DERIVATION(alg));
TEST_ASSERT(PSA_ALG_IS_PAKE(alg));
}
/* END_CASE */
/* BEGIN_CASE */
void key_type(int type_arg, int classification_flags)
{
psa_key_type_t type = type_arg;
key_type_classification(type, classification_flags);
/* For asymmetric types, check the corresponding pair/public type */
if (classification_flags & KEY_TYPE_IS_PUBLIC_KEY) {
psa_key_type_t pair_type = PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type);
TEST_EQUAL(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(pair_type), type);
key_type_classification(pair_type,
(classification_flags
& ~KEY_TYPE_IS_PUBLIC_KEY)
| KEY_TYPE_IS_KEY_PAIR);
TEST_EQUAL(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type), type);
}
if (classification_flags & KEY_TYPE_IS_KEY_PAIR) {
psa_key_type_t public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type);
TEST_EQUAL(PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(public_type), type);
key_type_classification(public_type,
(classification_flags
& ~KEY_TYPE_IS_KEY_PAIR)
| KEY_TYPE_IS_PUBLIC_KEY);
TEST_EQUAL(PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type), type);
}
}
/* END_CASE */
/* BEGIN_CASE */
void block_cipher_key_type(int type_arg, int block_size_arg)
{
psa_key_type_t type = type_arg;
size_t block_size = block_size_arg;
test_key_type(type_arg, KEY_TYPE_IS_UNSTRUCTURED);
TEST_EQUAL(type & PSA_KEY_TYPE_CATEGORY_MASK,
PSA_KEY_TYPE_CATEGORY_SYMMETRIC);
TEST_EQUAL(PSA_BLOCK_CIPHER_BLOCK_LENGTH(type), block_size);
/* Check that the block size is a power of 2. This is required, at least,
for PSA_ROUND_UP_TO_MULTIPLE(block_size, length) in crypto_sizes.h. */
TEST_ASSERT(((block_size - 1) & block_size) == 0);
}
/* END_CASE */
/* BEGIN_CASE */
void stream_cipher_key_type(int type_arg)
{
psa_key_type_t type = type_arg;
test_key_type(type_arg, KEY_TYPE_IS_UNSTRUCTURED);
TEST_EQUAL(type & PSA_KEY_TYPE_CATEGORY_MASK,
PSA_KEY_TYPE_CATEGORY_SYMMETRIC);
TEST_EQUAL(PSA_BLOCK_CIPHER_BLOCK_LENGTH(type), 1);
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_KEY_TYPE_ECC_PUBLIC_KEY:PSA_KEY_TYPE_ECC_KEY_PAIR */
void ecc_key_family(int curve_arg)
{
psa_ecc_family_t curve = curve_arg;
psa_key_type_t public_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve);
psa_key_type_t pair_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve);
TEST_PARITY(curve);
test_key_type(public_type, KEY_TYPE_IS_ECC | KEY_TYPE_IS_PUBLIC_KEY);
test_key_type(pair_type, KEY_TYPE_IS_ECC | KEY_TYPE_IS_KEY_PAIR);
TEST_EQUAL(PSA_KEY_TYPE_ECC_GET_FAMILY(public_type), curve);
TEST_EQUAL(PSA_KEY_TYPE_ECC_GET_FAMILY(pair_type), curve);
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_KEY_TYPE_DH_PUBLIC_KEY:PSA_KEY_TYPE_DH_KEY_PAIR */
void dh_key_family(int group_arg)
{
psa_dh_family_t group = group_arg;
psa_key_type_t public_type = PSA_KEY_TYPE_DH_PUBLIC_KEY(group);
psa_key_type_t pair_type = PSA_KEY_TYPE_DH_KEY_PAIR(group);
TEST_PARITY(group);
test_key_type(public_type, KEY_TYPE_IS_DH | KEY_TYPE_IS_PUBLIC_KEY);
test_key_type(pair_type, KEY_TYPE_IS_DH | KEY_TYPE_IS_KEY_PAIR);
TEST_EQUAL(PSA_KEY_TYPE_DH_GET_FAMILY(public_type), group);
TEST_EQUAL(PSA_KEY_TYPE_DH_GET_FAMILY(pair_type), group);
}
/* END_CASE */
/* BEGIN_CASE */
void lifetime(int lifetime_arg, int classification_flags,
int persistence_arg, int location_arg)
{
psa_key_lifetime_t lifetime = lifetime_arg;
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(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);
}
/* END_CASE */