diff --git a/sys/include/psa_crypto/psa/crypto_sizes.h b/sys/include/psa_crypto/psa/crypto_sizes.h index bdcc1be479..4303ad6bc3 100644 --- a/sys/include/psa_crypto/psa/crypto_sizes.h +++ b/sys/include/psa_crypto/psa/crypto_sizes.h @@ -367,7 +367,24 @@ extern "C" { * recognized, return 0. An implementation can return either 0 or the correct size for a * hash algorithm that it recognizes, but does not support. */ -#define PSA_HASH_BLOCK_LENGTH(alg) /* implementation-defined value */ +#define PSA_HASH_BLOCK_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 : \ + 0) /** * @brief The size of the output of @ref psa_hash_compute() and @ref psa_hash_finish(), in bytes. @@ -439,7 +456,30 @@ extern "C" { * * See also @ref PSA_MAC_LENGTH(). */ -#define PSA_MAC_MAX_SIZE (PSA_HASH_MAX_SIZE) +#if (IS_USED(MODULE_PSA_MAC_HMAC_SHA_512) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA3_512)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_SHA3_512)) /* 64 */ +#elif (IS_USED(MODULE_PSA_MAC_HMAC_SHA_384) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA3_384)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_SHA3_384)) /* 48 */ +#elif (IS_USED(MODULE_PSA_MAC_HMAC_SHA_256) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA_512_256) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA3_256)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_SHA3_256)) /* 32 */ +#elif (IS_USED(MODULE_PSA_MAC_HMAC_SHA_224) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA_512_224) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA3_224)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_SHA3_224)) /* 28 */ +#elif (IS_USED(MODULE_PSA_MAC_HMAC_RIPEMD160) || \ + IS_USED(MODULE_PSA_MAC_HMAC_SHA_1)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_SHA_1)) /* 20 */ +#elif (IS_USED(MODULE_PSA_MAC_HMAC_MD2) || \ + IS_USED(MODULE_PSA_MAC_HMAC_MD4) || \ + IS_USED(MODULE_PSA_MAC_HMAC_MD5)) +#define PSA_MAC_MAX_SIZE (PSA_HASH_LENGTH(PSA_ALG_MD5)) /* 16 */ +#else +#define PSA_MAC_MAX_SIZE 0 +#endif /** * @brief The block size of a block cipher. diff --git a/sys/include/psa_crypto/psa/crypto_types.h b/sys/include/psa_crypto/psa/crypto_types.h index fa343e7a5d..246226cd7e 100644 --- a/sys/include/psa_crypto/psa/crypto_types.h +++ b/sys/include/psa_crypto/psa/crypto_types.h @@ -26,6 +26,8 @@ extern "C" { #include +#include "psa/error.h" + /** * @brief For encrypt-decrypt functions, whether the operation is an encryption * or a decryption. @@ -319,15 +321,6 @@ typedef struct psa_aead_operation_s psa_aead_operation_t; */ typedef struct psa_mac_operation_s psa_mac_operation_t; -/** - * @brief Function return status. - * - * @details This is either @ref PSA_SUCCESS, which is zero, indicating success; or a small - * negative value indicating that an error occurred. Errors are encoded as one of - * the @c PSA_ERROR_xxx values defined here. - */ -typedef int32_t psa_status_t; - /** * @brief The type of the state data structure for multipart hash operations. * diff --git a/sys/include/psa_crypto/psa/crypto_values.h b/sys/include/psa_crypto/psa/crypto_values.h index 7de569dc0e..64a1e4f783 100644 --- a/sys/include/psa_crypto/psa/crypto_values.h +++ b/sys/include/psa_crypto/psa/crypto_values.h @@ -3354,118 +3354,6 @@ extern "C" { */ #define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE /* implementation-defined value */ -/** - * @brief The action was completed successfully. - */ -#define PSA_SUCCESS ((psa_status_t)0) - -/** - * @brief An error occurred that does not correspond to any defined failure cause. - */ -#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) - -/** - * @brief The requested operation or a parameter is not supported by this implementation. - */ -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) - -/** - * @brief The requested action is denied by a policy. - */ -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) - -/** - * @brief An output buffer is too small. - */ -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) - -/** - * @brief Asking for an item that already exists. - */ -#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) - -/** - * @brief Asking for an item that doesn’t exist. - */ -#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) - -/** - * @brief The requested action cannot be performed in the current state. - */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) - -/** - * @brief The parameters passed to the function are invalid. - */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) - -/** - * @brief There is not enough runtime memory. - */ -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) - -/** - * @brief There is not enough persistent storage. - */ -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) - -/** - * @brief There was a communication failure inside the implementation. - */ -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) - -/** - * @brief There was a storage failure that might have led to data loss. - */ -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) - -/** - * @brief Stored data has been corrupted. - */ -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - -/** - * @brief Data read from storage is not valid for the implementation. - */ -#define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) - -/** - * @brief A hardware failure was detected. - */ -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) - -/** - * @brief A tampering attempt was detected. - */ -#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) - -/** - * @brief There is not enough entropy to generate random data needed - * for the requested action. - */ -#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) - -/** - * @brief The signature, MAC or hash is incorrect. - */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) - -/** - * @brief The decrypted padding is incorrect. - */ -#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) - -/** - * @brief Return this error when there’s insufficient data when - * attempting to read from a resource. - */ -#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) - -/** - * @brief The key identifier is not valid. - */ -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) - #ifdef __cplusplus } #endif diff --git a/sys/include/psa_crypto/psa/error.h b/sys/include/psa_crypto/psa/error.h new file mode 100644 index 0000000000..26a3aa4f02 --- /dev/null +++ b/sys/include/psa_crypto/psa/error.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2024 TU Dresden + * Copyright (C) 2021 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup sys_psa_crypto + * @{ + * + * @file error.h + * @brief Error definitions for the PSA Crypto API + * + * @details This header file is also compatible with the PSA Certified Status code API. + * + * @author Armin Wolf + * @author Lena Boeckmann + * + */ + +#ifndef PSA_CRYPTO_PSA_ERROR_H +#define PSA_CRYPTO_PSA_ERROR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @brief Status code type used for all PSA Certified APIs. + * + * @details This is either @ref PSA_SUCCESS, which is zero, indicating success; or a small + * negative value indicating that an error occurred. Errors are encoded as one of + * the @c PSA_ERROR_xxx values defined here. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/** + * @brief Status code to indicate general success. + */ +#define PSA_SUCCESS ((psa_status_t)0) + +/** + * @brief Status code that indicates a programmer error in the client. + */ +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) + +/** + * @brief Status code that indicates that the caller is not permitted to connect to a Service. + */ +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) + +/** + * @brief Status code that indicates that the caller cannot connect to a service. + */ +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) + +/** + * @brief Status code that indicates an error that does not correspond to any defined + * failure cause. + */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** + * @brief Status code that indicates that the requested action is denied by a policy. + */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** + * @brief Status code that indicates that the requested operation or a parameter is not supported. + */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** + * @brief Status code that indicates that the parameters passed to the function are invalid. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** + * @brief Status code that indicates that a handle parameter is not valid. + * + * @details Usually means that a key identifier does not refer to an existing key. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/** + * @brief Status code that indicates that the requested action cannot be performed in the + * current state. + * + * @details Multi-part operations return this error when one of the functions is called out + * of sequence. We also return this error if the caller has not initialized the library + * by a call to @ref psa_crypto_init(). + */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** + * @brief Status code that indicates that an output buffer parameter is too small. + * + * @details Applications can call the @c PSA_xxx_SIZE macros listed in the function description to + * determine a sufficient buffer size. + */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** + * @brief Status code that indicates that an identifier or index is already in use. + */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** + * @brief Status code that indicates that an identified resource does not exist. + */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** + * @brief Status code that indicates that there is not enough runtime memory. + */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** + * @brief Status code that indicates that there is not enough persistent storage. + */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** + * @brief Status code that indicates that a data source has insufficient capacity left. + */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** + * @brief Status code that indicates an error within the service. + */ +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) + +/** + * @brief Status code that indicates a communication failure between the function and another + * service or component. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** + * @brief Status code that indicates a storage failure that may have led to data loss. + * + * @details When a storage failure occurs, it is no longer possible to ensure the global + * integrity of the keystore. Access to other data might fail even if the data + * is still readable but its integrity cannot be guaranteed. + */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** + * @brief Status code that indicates that a hardware failure was detected. + */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** + * @brief Status code that indicates that there is not enough entropy to generate random data + * needed for the requested action. + */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** + * @brief Status code that indicates that a signature, MAC or hash is incorrect. + */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** + * @brief Status code that indicates that the decrypted padding is incorrect. + */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** + * @brief Status code that indicates that internal data has been tampered with. + * + * @details This error code is intended as a last resort when a security breach is detected + * and it is unsure whether the keystore data is still protected. Only return this + * error code to report an alarm from a tampering detector, to indicate that the + * confidentiality of stored data can no longer be guaranteed, or to indicate that + * the integrity of previously returned data is now considered compromised. + */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** + * @brief Status code that indicates that stored data has been corrupted. + * + * @details When a storage failure occurs, it is no longer possible to ensure the global integrity + * of the keystore. Depending on the global integrity guarantees, access to other data + * might fail even if the data is still readable but its integrity cannot be guaranteed. + */ +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +/** + * @brief Status code that indicates that data read from storage is not valid for the + * implementation. + */ +#define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) + +/** + * @brief Status code that indicates that the requested operation is interruptible, and still + * has work to do. + * + * @details This status code does not mean that the operation has failed or that it has succeeded. + * The operation must be repeated until it completes with either success or failure. + */ +#define PSA_OPERATION_INCOMPLETE ((psa_status_t)-248) + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_PSA_ERROR_H */ +/** @} */ diff --git a/sys/psa_crypto/doc.txt b/sys/psa_crypto/doc.txt index 773f22d893..27de4e83d8 100644 --- a/sys/psa_crypto/doc.txt +++ b/sys/psa_crypto/doc.txt @@ -12,7 +12,8 @@ * About {#About} * ===== * This module implements the PSA Cryptography API Version 1.1 as specified - * [here](https://armmbed.github.io/mbed-crypto/html/). + * [here](https://armmbed.github.io/mbed-crypto/html/) and the PSA Status code API Version 1.0 + * as specified [here](https://arm-software.github.io/psa-api/status-code/1.0/). * It provides an OS level access to cryptographic operations and supports software and hardware * backends as well as the use of secure elements. * The API automatically builds a hardware backend for an operation, if there's one available, diff --git a/sys/psa_crypto/psa_crypto.c b/sys/psa_crypto/psa_crypto.c index 90b573840d..0f35b3fdbf 100644 --- a/sys/psa_crypto/psa_crypto.c +++ b/sys/psa_crypto/psa_crypto.c @@ -1133,6 +1133,15 @@ static psa_status_t psa_start_key_creation(psa_key_creation_method_t method, slot = *p_slot; slot->attr = *attributes; + /* See 9.5.2. Key usage flags */ + if (slot->attr.policy.usage & PSA_KEY_USAGE_SIGN_HASH) { + slot->attr.policy.usage |= PSA_KEY_USAGE_SIGN_MESSAGE; + } + + if (slot->attr.policy.usage & PSA_KEY_USAGE_VERIFY_HASH) { + slot->attr.policy.usage |= PSA_KEY_USAGE_VERIFY_MESSAGE; + } + if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { slot->attr.id = key_id; } diff --git a/tests/sys/psa_crypto/main.c b/tests/sys/psa_crypto/main.c index f7c19f80f2..0feffca843 100644 --- a/tests/sys/psa_crypto/main.c +++ b/tests/sys/psa_crypto/main.c @@ -111,6 +111,75 @@ cleanup: TEST_ASSERT_PSA_CONTINUE(psa_hash_abort(&op2)); } +/** + * Importing keys with the usage flags PSA_KEY_USAGE_SIGN_HASH/PSA_KEY_USAGE_VERIFY_HASH + * should automatically set the usage flags PSA_KEY_USAGE_SIGN_MESSAGE/PSA_KEY_USAGE_VERIFY_MESSAGE + * on the key. + */ +static void test_key_import_usage_flags(void) +{ + psa_key_attributes_t attributes = psa_key_attributes_init(); + psa_key_attributes_t key_attrs; + const uint8_t key[32] = { 0 }; + psa_key_usage_t key_usage; + psa_key_id_t key_id; + + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_512)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(key))); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + TEST_ASSERT_PSA_RETURN(psa_crypto_init()); + TEST_ASSERT_PSA_RETURN(psa_import_key(&attributes, key, sizeof(key), &key_id)); + + TEST_ASSERT_PSA_CLEANUP(psa_get_key_attributes(key_id, &key_attrs)); + key_usage = psa_get_key_usage_flags(&key_attrs); + + TEST_ASSERT_PSA_RETURN(psa_destroy_key(key_id)); + + TEST_ASSERT(key_usage & PSA_KEY_USAGE_SIGN_MESSAGE); + TEST_ASSERT(key_usage & PSA_KEY_USAGE_VERIFY_MESSAGE); + + return; + +cleanup: + TEST_ASSERT_PSA_CONTINUE(psa_destroy_key(key_id)); +} + +/** + * Generating keys with the usage flags PSA_KEY_USAGE_SIGN_HASH/PSA_KEY_USAGE_VERIFY_HASH + * should automatically set the usage flags PSA_KEY_USAGE_SIGN_MESSAGE/PSA_KEY_USAGE_VERIFY_MESSAGE + * on the key. + */ +static void test_key_generate_usage_flags(void) +{ + psa_key_attributes_t attributes = psa_key_attributes_init(); + psa_key_attributes_t key_attrs; + psa_key_usage_t key_usage; + psa_key_id_t key_id; + + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_512)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(32)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + TEST_ASSERT_PSA_RETURN(psa_crypto_init()); + TEST_ASSERT_PSA_RETURN(psa_generate_key(&attributes, &key_id)); + + TEST_ASSERT_PSA_CLEANUP(psa_get_key_attributes(key_id, &key_attrs)); + key_usage = psa_get_key_usage_flags(&key_attrs); + + TEST_ASSERT_PSA_RETURN(psa_destroy_key(key_id)); + + TEST_ASSERT(key_usage & PSA_KEY_USAGE_SIGN_MESSAGE); + TEST_ASSERT(key_usage & PSA_KEY_USAGE_VERIFY_MESSAGE); + + return; + +cleanup: + TEST_ASSERT_PSA_CONTINUE(psa_destroy_key(key_id)); +} + /** * Exporting and re-importing a private Ed25519 key should result in the same public key and signature. */ @@ -227,6 +296,8 @@ static Test *tests_psa_crypto(void) EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_init_twice), new_TestFixture(test_hash_interleaved), + new_TestFixture(test_key_import_usage_flags), + new_TestFixture(test_key_generate_usage_flags), new_TestFixture(test_exported_key_is_identical_when_imported_again_ed25519), new_TestFixture(test_export_public_key_ed25519), };