| /* 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 */ |