diff --git a/sys/include/psa_crypto/psa/crypto_sizes.h b/sys/include/psa_crypto/psa/crypto_sizes.h index fcd0f8ba23..e82f75789f 100644 --- a/sys/include/psa_crypto/psa/crypto_sizes.h +++ b/sys/include/psa_crypto/psa/crypto_sizes.h @@ -62,13 +62,16 @@ extern "C" { #elif (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P256R1) || \ IS_USED(MODULE_PSA_ASYMMETRIC_ECC_ED25519) || \ IS_USED(MODULE_PSA_CIPHER_AES_256_CBC) || \ + IS_USED(MODULE_PSA_AEAD_AES_256_CCM) || \ IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A_ECC_P256) || \ IS_USED(MODULE_PSA_CIPHER_CHACHA20)) #define CONFIG_PSA_MAX_KEY_SIZE 32 #elif (IS_USED(MODULE_PSA_CIPHER_AES_192_CBC) || \ + IS_USED(MODULE_PSA_AEAD_AES_192_CCM) || \ IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P192R1)) #define CONFIG_PSA_MAX_KEY_SIZE 24 #elif (IS_USED(MODULE_PSA_CIPHER_AES_128_CBC)) || \ + (IS_USED(MODULE_PSA_AEAD_AES_128_CCM)) || \ (IS_USED(MODULE_PSA_CIPHER_AES_128_ECB)) #define CONFIG_PSA_MAX_KEY_SIZE 16 #else @@ -124,6 +127,52 @@ extern "C" { #define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \ /* implementation-defined value */ +/** + * @brief The length of a tag for an AEAD algorithm, in bytes. + * + * @details This is the size of the tag output from @ref psa_aead_finish(). + * If the size of the tag buffer is at least this large, it is guaranteed that + * @ref psa_aead_finish() will not fail due to an insufficient tag buffer size. + * + * See also @ref PSA_AEAD_TAG_MAX_SIZE. + * + * @param key_type The type of the AEAD key. + * @param key_bits The size of the AEAD key in bits. + * @param alg An AEAD algorithm: a value of type @ref psa_algorithm_t such that + * @ref PSA_ALG_IS_AEAD(@p alg) is true. + * + * @return The tag length for the specified algorithm and key. + * 0 if the AEAD algorithm does not have an identified tag that can be distinguished from + * the rest of the ciphertext. + * 0 if the AEAD algorithm is not recognized or not supported. + */ +#define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & 0x003f0000) >> 16) : \ + ((void) (key_type), (void) (key_bits), 0)) + +/** + * @brief A sufficient buffer size for storing the tag output by @ref psa_aead_finish(), + * for any of the supported key types and AEAD algorithms. + * + * @details If the size of the tag buffer is at least this large, it is guaranteed that + * @ref psa_aead_finish() will not fail due to an insufficient buffer size. + * + * See also @ref PSA_AEAD_TAG_LENGTH(). + */ +#define PSA_AEAD_TAG_MAX_SIZE (16) + +/** + * @brief A sufficient buffer size for storing the tag output by @ref psa_aead_finish(), + * for AES key types and CCM algorithms. + * + * @details If the size of the tag buffer is at least this large, it is guaranteed that + * @ref psa_aead_finish() will not fail due to an insufficient buffer size. + * + * See also @ref PSA_AEAD_TAG_LENGTH(). + */ +#define PSA_AES_CCM_TAG_MAX_SIZE (16) + /** * @brief A sufficient plaintext buffer size for @ref psa_aead_decrypt(), in bytes. * @@ -143,7 +192,9 @@ extern "C" { * are incompatible. */ #define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \ -/* implementation-defined value */ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + ((ciphertext_length) > PSA_AEAD_TAG_LENGTH(key_type, 0, alg)) ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(key_type, 0, alg) : 0) /** * @brief A sufficient ciphertext buffer size for @ref psa_aead_encrypt(), @@ -158,7 +209,7 @@ extern "C" { * @param plaintext_length Size of the plaintext in bytes. */ #define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length) \ -/* implementation-defined value */ + ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE) /** * @brief A sufficient ciphertext buffer size for @ref psa_aead_encrypt(), in bytes. @@ -179,7 +230,8 @@ extern "C" { * are incompatible. */ #define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ -/* implementation-defined value */ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(key_type, 0, alg) : 0) /** * @brief A sufficient ciphertext buffer size for @ref psa_aead_finish(), @@ -232,7 +284,13 @@ extern "C" { * 0 if the key type or AEAD algorithm is not recognized, not supported or the parameters * are incompatible. */ -#define PSA_AEAD_NONCE_LENGTH(key_type, alg) /* implementation-defined value */ +#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ + ((PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 && \ + ((PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_CCM) || \ + (PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_CCM))) || \ + (key_type == PSA_KEY_TYPE_CHACHA20 && \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_CHACHA20_POLY1305) ? \ + 12 : 0) /** * @brief A sufficient buffer size for storing the nonce generated by @@ -243,40 +301,7 @@ extern "C" { * * See also @ref PSA_AEAD_NONCE_LENGTH(). */ -#define PSA_AEAD_NONCE_MAX_SIZE /* implementation-defined value */ - -/** - * @brief The length of a tag for an AEAD algorithm, in bytes. - * - * @details This is the size of the tag output from @ref psa_aead_finish(). - * If the size of the tag buffer is at least this large, it is guaranteed that - * @ref psa_aead_finish() will not fail due to an insufficient tag buffer size. - * - * See also @ref PSA_AEAD_TAG_MAX_SIZE. - * - * @param key_type The type of the AEAD key. - * @param key_bits The size of the AEAD key in bits. - * @param alg An AEAD algorithm: a value of type @ref psa_algorithm_t such that - * @ref PSA_ALG_IS_AEAD(@p alg) is true. - * - * @return The tag length for the specified algorithm and key. - * 0 if the AEAD algorithm does not have an identified tag that can be distinguished from - * the rest of the ciphertext. - * 0 if the AEAD algorithm is not recognized or not supported. - */ -#define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ -/* implementation-defined value */ - -/** - * @brief A sufficient buffer size for storing the tag output by @ref psa_aead_finish(), - * for any of the supported key types and AEAD algorithms. - * - * @details If the size of the tag buffer is at least this large, it is guaranteed that - * @ref psa_aead_finish() will not fail due to an insufficient buffer size. - * - * See also @ref PSA_AEAD_TAG_LENGTH(). - */ -#define PSA_AEAD_TAG_MAX_SIZE /* implementation-defined value */ +#define PSA_AEAD_NONCE_MAX_SIZE (13) /** * @brief A sufficient output buffer size for @ref psa_aead_update(), for any of the supported key diff --git a/sys/psa_crypto/Makefile.dep b/sys/psa_crypto/Makefile.dep index e4ab02259d..34117d7c8a 100644 --- a/sys/psa_crypto/Makefile.dep +++ b/sys/psa_crypto/Makefile.dep @@ -143,6 +143,75 @@ ifneq (,$(filter psa_cipher_aes_192_cbc_backend_riot,$(USEMODULE))) USEMODULE += psa_riot_cipher_aes_192_cbc endif +# AEAD +ifneq (,$(filter psa_aead,$(USEMODULE))) + USEMODULE += psa_key_management +endif + +## AES-128-CCM +ifneq (,$(filter psa_aead_aes_128_ccm,$(USEMODULE))) + ifeq (,$(filter psa_aead_aes_128_ccm_custom_backend,$(USEMODULE))) + FEATURES_OPTIONAL += periph_aead_aes_128_ccm + include $(RIOTMAKE)/features_check.inc.mk + # HACK: Due to kconfig migration, may cause problems + ifneq (,$(filter periph_aead_aes_128_ccm,$(FEATURES_USED))) + USEMODULE += psa_aead_aes_128_ccm_backend_periph + else + USEMODULE += psa_aead_aes_128_ccm_backend_cifra + endif + endif +endif +ifneq (,$(filter psa_aead_aes_128_ccm_backend_periph,$(USEMODULE))) + FEATURES_REQUIRED += periph_aead_aes_128_ccm +endif +ifneq (,$(filter psa_aead_aes_128_ccm_backend_tinycrypt,$(USEMODULE))) + USEPKG += tinycrypt + USEMODULE += psa_tinycrypt + USEMODULE += psa_tinycrypt_aes_ccm +endif + +## AES-192-CCM +ifneq (,$(filter psa_aead_aes_192_ccm,$(USEMODULE))) + ifeq (,$(filter psa_aead_aes_192_ccm_custom_backend,$(USEMODULE))) + FEATURES_OPTIONAL += periph_aead_aes_192_ccm + include $(RIOTMAKE)/features_check.inc.mk + # HACK: Due to kconfig migration, may cause problems + ifneq (,$(filter periph_aead_aes_192_ccm,$(FEATURES_USED))) + USEMODULE += psa_aead_aes_192_ccm_backend_periph + else + USEMODULE += psa_aead_aes_192_ccm_backend_cifra + endif + endif +endif +ifneq (,$(filter psa_aead_aes_192_ccm_backend_periph,$(USEMODULE))) + FEATURES_REQUIRED += periph_aead_aes_192_ccm +endif + +## AES-256-CCM +ifneq (,$(filter psa_aead_aes_256_ccm,$(USEMODULE))) + ifeq (,$(filter psa_aead_aes_256_ccm_custom_backend,$(USEMODULE))) + FEATURES_OPTIONAL += periph_aead_aes_256_ccm + include $(RIOTMAKE)/features_check.inc.mk + # HACK: Due to kconfig migration, may cause problems + ifneq (,$(filter periph_aead_aes_256_ccm,$(FEATURES_USED))) + USEMODULE += psa_aead_aes_256_ccm_backend_periph + else + USEMODULE += psa_aead_aes_256_ccm_backend_cifra + endif + endif +endif +ifneq (,$(filter psa_aead_aes_256_ccm_backend_periph,$(USEMODULE))) + FEATURES_REQUIRED += periph_aead_aes_256_ccm +endif + +## Cifra supports all of them +ifneq (,$(filter psa_aead_aes_%_ccm_backend_cifra,$(USEMODULE))) + USEPKG += cifra + USEMODULE += psa_cifra + USEMODULE += psa_cifra_aes_ccm +endif + + ## ChaCha20 ifneq (,$(filter psa_cipher_chacha20,$(USEMODULE))) ifeq (,$(filter psa_cipher_chacha20_custom_backend,$(USEMODULE))) diff --git a/sys/psa_crypto/Makefile.include b/sys/psa_crypto/Makefile.include index 5d8bbaf2ca..10b64ca84f 100644 --- a/sys/psa_crypto/Makefile.include +++ b/sys/psa_crypto/Makefile.include @@ -97,6 +97,43 @@ ifneq (,$(filter psa_cipher_chacha20,$(USEMODULE))) endif endif +## AEAD +PSEUDOMODULES += psa_aead +PSEUDOMODULES += psa_aead_aes_128_ccm +PSEUDOMODULES += psa_aead_aes_128_ccm_backend_periph +PSEUDOMODULES += psa_aead_aes_128_ccm_backend_cifra +PSEUDOMODULES += psa_aead_aes_128_ccm_backend_tinycrypt +PSEUDOMODULES += psa_aead_aes_128_ccm_custom_backend + +# check that one and only one backend has been selected +ifneq (,$(filter psa_aead_aes_128_ccm,$(USEMODULE))) + ifneq (1,$(call backends,psa_aead_aes_128_ccm)) + $(error "One (and only one) backend should be selected for psa_aead_aes_128_ccm") + endif +endif + +PSEUDOMODULES += psa_aead_aes_192_ccm +PSEUDOMODULES += psa_aead_aes_192_ccm_backend_cifra +PSEUDOMODULES += psa_aead_aes_192_ccm_custom_backend + +# check that one and only one backend has been selected +ifneq (,$(filter psa_aead_aes_192_ccm,$(USEMODULE))) + ifneq (1,$(call backends,psa_aead_aes_192_ccm)) + $(error "One (and only one) backend should be selected for psa_aead_aes_192_ccm") + endif +endif + +PSEUDOMODULES += psa_aead_aes_256_ccm +PSEUDOMODULES += psa_aead_aes_256_ccm_backend_cifra +PSEUDOMODULES += psa_aead_aes_256_ccm_custom_backend + +# check that one and only one backend has been selected +ifneq (,$(filter psa_aead_aes_256_ccm,$(USEMODULE))) + ifneq (1,$(call backends,psa_aead_aes_256_ccm)) + $(error "One (and only one) backend should be selected for psa_aead_aes_256_ccm") + endif +endif + ## Hash PSEUDOMODULES += psa_hash PSEUDOMODULES += psa_hash_md5 diff --git a/sys/psa_crypto/doc.md b/sys/psa_crypto/doc.md index 78b560063a..b646373017 100644 --- a/sys/psa_crypto/doc.md +++ b/sys/psa_crypto/doc.md @@ -269,6 +269,25 @@ names in uppercase and add the prefix `CONFIG_MODULE_` to all of them. - psa_asymmetric_ecc_ed25519_custom_backend - psa_asymmetric_ecc_ed25519_backend_c25519 +### AEAD +- Base: psa_aead + +#### AES CCM +- psa_aead_aes_128_ccm +- psa_aead_aes_128_ccm_backend_periph +- psa_aead_aes_128_ccm_backend_cifra +- psa_aead_aes_128_ccm_backend_tinycrypt + +@note Be aware that the tinycrypt only allows a nonce size of 13. + +- psa_aead_aes_128_ccm_custom_backend +- psa_aead_aes_192_ccm +- psa_aead_aes_192_ccm_backend_cifra +- psa_aead_aes_192_ccm_custom_backend +- psa_aead_aes_256_ccm +- psa_aead_aes_256_ccm_backend_cifra +- psa_aead_aes_256_ccm_custom_backend + ### Ciphers - Base: psa_cipher diff --git a/sys/psa_crypto/include/psa_aead.h b/sys/psa_crypto/include/psa_aead.h new file mode 100644 index 0000000000..9b123b7037 --- /dev/null +++ b/sys/psa_crypto/include/psa_aead.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2025 TU Dresden + * + * 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 + * @defgroup sys_psa_crypto_aead PSA Wrapper Functions: AEAD + * @{ + * + * @file psa_aead.h + * @brief Function declarations for low level wrapper functions for aead operations. + * + * @author Lukas Luger + * + */ +#ifndef PSA_AEAD_H +#define PSA_AEAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/crypto.h" +#include "psa/crypto_contexts.h" + +#if IS_USED(MODULE_PSA_AEAD_AES_128_CCM) || defined(DOXYGEN) +/** + * @brief Low level wrapper function to call a driver for an AES 128 CCM encryption. + * See @ref psa_aead_encrypt() + */ +psa_status_t psa_aead_aes_128_ccm_encrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *plaintext, + size_t plaintext_length, uint8_t *ciphertext, + size_t ciphertext_size, size_t *ciphertext_length); + +/** + * @brief Low level wrapper function to call a driver for an AES 128 CCM decryption. + * See @ref psa_aead_decrypt() + */ +psa_status_t psa_aead_aes_128_ccm_decrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *ciphertext, + size_t ciphertext_length, uint8_t *plaintext, + size_t plaintext_size, size_t *plaintext_length); +#endif /* MODULE_PSA_AEAD_AES_128_CCM */ + +#if IS_USED(MODULE_PSA_AEAD_AES_192_CCM) || defined(DOXYGEN) +/** + * @brief Low level wrapper function to call a driver for an AES 192 CCM encryption. + * See @ref psa_aead_encrypt() + */ +psa_status_t psa_aead_aes_192_ccm_encrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *plaintext, + size_t plaintext_length, uint8_t *ciphertext, + size_t ciphertext_size, size_t *ciphertext_length); + +/** +* @brief Low level wrapper function to call a driver for an AES 192 CCM decryption. +* See @ref psa_aead_decrypt() +*/ +psa_status_t psa_aead_aes_192_ccm_decrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *ciphertext, + size_t ciphertext_length, uint8_t *plaintext, + size_t plaintext_size, size_t *plaintext_length); +#endif /* MODULE_PSA_AEAD_AES_192_CCM */ + +#if IS_USED(MODULE_PSA_AEAD_AES_256_CCM) || defined(DOXYGEN) +/** + * @brief Low level wrapper function to call a driver for an AES 256 CCM encryption. + * See @ref psa_aead_encrypt() + */ +psa_status_t psa_aead_aes_256_ccm_encrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *plaintext, + size_t plaintext_length, uint8_t *ciphertext, + size_t ciphertext_size, size_t *ciphertext_length); + +/** +* @brief Low level wrapper function to call a driver for an AES 256 CCM decryption. +* See @ref psa_aead_decrypt() +*/ +psa_status_t psa_aead_aes_256_ccm_decrypt(const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_length, + uint8_t tag_length, const uint8_t *nonce, + size_t nonce_length, const uint8_t *additional_data, + size_t additional_data_length, const uint8_t *ciphertext, + size_t ciphertext_length, uint8_t *plaintext, + size_t plaintext_size, size_t *plaintext_length); +#endif /* MODULE_PSA_AEAD_AES_256_CCM */ +#ifdef __cplusplus +} +#endif + +#endif /* PSA_AEAD_H */ +/** @} */ diff --git a/sys/psa_crypto/include/psa_crypto_algorithm_dispatch.h b/sys/psa_crypto/include/psa_crypto_algorithm_dispatch.h index 4cd5cc9692..3a1da59c5c 100644 --- a/sys/psa_crypto/include/psa_crypto_algorithm_dispatch.h +++ b/sys/psa_crypto/include/psa_crypto_algorithm_dispatch.h @@ -155,6 +155,41 @@ psa_status_t psa_algorithm_dispatch_cipher_decrypt( const psa_key_attributes_t * size_t *output_length); #endif /* MODULE_PSA_CIPHER */ +#if IS_USED(MODULE_PSA_AEAD) +/** + * @brief Dispatch a aead encrypt function to a specific backend. + * See @ref psa_aead_encrypt() + */ +psa_status_t psa_algorithm_dispatch_aead_encrypt( const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** + * @brief Dispatch a aead decrypt function to a specific backend. + * See @ref psa_aead_decrypt() + */ +psa_status_t psa_algorithm_dispatch_aead_decrypt( const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); +#endif /* MODULE_PSA_AEAD */ #if IS_USED(MODULE_PSA_MAC) /** * @brief Dispatch a mac computation function to a specific backend. diff --git a/sys/psa_crypto/include/psa_crypto_location_dispatch.h b/sys/psa_crypto/include/psa_crypto_location_dispatch.h index f6d9231a45..314fc7208d 100644 --- a/sys/psa_crypto/include/psa_crypto_location_dispatch.h +++ b/sys/psa_crypto/include/psa_crypto_location_dispatch.h @@ -166,6 +166,41 @@ psa_status_t psa_location_dispatch_cipher_decrypt( const psa_key_attributes_t * size_t *output_length); #endif /* MODULE_PSA_CIPHER */ +#if IS_USED(MODULE_PSA_AEAD) +/** + * @brief Dispatch a aead encrypt function to a specific backend. + * See @ref psa_aead_encrypt() + */ +psa_status_t psa_location_dispatch_aead_encrypt(const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); +/** + * @brief Dispatch a aead decrypt function to a specific backend. + * See @ref psa_aead_decrypt() + */ +psa_status_t psa_location_dispatch_aead_decrypt(const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); +#endif /* MODULE_PSA_AEAD */ + /** * @brief Dispatch call of a random number generator to a specific backend. * See psa_generate_random() diff --git a/sys/psa_crypto/include/psa_crypto_operation_encoder.h b/sys/psa_crypto/include/psa_crypto_operation_encoder.h index 7dcee3ad64..d73920172a 100644 --- a/sys/psa_crypto/include/psa_crypto_operation_encoder.h +++ b/sys/psa_crypto/include/psa_crypto_operation_encoder.h @@ -49,6 +49,17 @@ typedef enum { PSA_STREAM_CIPHER_CHACHA20 } psa_cipher_op_t; +/** + * @brief Enum encoding available aead operations. + * + * @details To be expanded with the development of this implementation. + */ +typedef enum { + PSA_CCM_AES_128, + PSA_CCM_AES_192, + PSA_CCM_AES_256 +} psa_aead_op_t; + /** * @brief Enum encoding available asymmetric key types and sizes. * @@ -126,6 +137,23 @@ typedef enum { PSA_INVALID_OPERATION) : \ PSA_INVALID_OPERATION) +/** + * @brief Combine key type and size with a PSA_ALG_CCM algorithm + * + * @param type Key type of type @ref psa_key_type_t + * @param bits Size of the used key of type @ref psa_key_bits_t + * + * @return @ref psa_aead_op_t + * @return @ref PSA_INVALID_OPERATION @c alg, @c bits and @c type are not compatible + */ +#define GET_AES_CCM_OPERATION(type, bits) \ + ((type == PSA_KEY_TYPE_AES) ? \ + ((bits == 128) ? PSA_CCM_AES_128 : \ + (bits == 192) ? PSA_CCM_AES_192 : \ + (bits == 256) ? PSA_CCM_AES_256 : \ + PSA_INVALID_OPERATION) : \ + PSA_INVALID_OPERATION) + /** * @brief Combine key type and size with a PSA_ALG_CBC_PKCS7 algorithm * @@ -233,6 +261,20 @@ typedef enum { (alg == PSA_ALG_XTS) ? GET_XTS_OPERATION(type, bits) : \ PSA_INVALID_OPERATION) +/** + * @brief Map algorithm, key size and type to a specific operation. + * + * @param alg Algorithm of type @ref psa_algorithm_t. + * @param type Key type of type @ref psa_key_type_t + * @param bits Size of the used key of type @ref psa_key_bits_t + * + * @return @ref psa_aead_op_t + * @return @ref PSA_INVALID_OPERATION @c alg, @c bits and @c type are not compatible + */ +#define PSA_ENCODE_AEAD_OPERATION(alg, type, bits) \ + ((PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) == PSA_ALG_CCM) ? \ + GET_AES_CCM_OPERATION(type, bits) : PSA_INVALID_OPERATION) + #ifdef __cplusplus } #endif diff --git a/sys/psa_crypto/psa_crypto.c b/sys/psa_crypto/psa_crypto.c index ad9183dc51..e7e638200c 100644 --- a/sys/psa_crypto/psa_crypto.c +++ b/sys/psa_crypto/psa_crypto.c @@ -71,6 +71,13 @@ static inline int constant_time_memcmp(const uint8_t *a, const uint8_t *b, size_ } #endif /* MODULE_PSA_HASH */ +#if IS_USED(MODULE_PSA_KEY_MANAGEMENT) +static psa_status_t psa_get_and_lock_key_slot_with_policy(psa_key_id_t id, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg); +#endif /* MODULE_PSA_KEY_MANAGEMENT */ + const char *psa_status_to_humanly_readable(psa_status_t status) { switch (status) { @@ -116,6 +123,8 @@ const char *psa_status_to_humanly_readable(psa_status_t status) return "PSA_ERROR_INSUFFICIENT_DATA"; case PSA_ERROR_INVALID_HANDLE: return "PSA_ERROR_INVALID_HANDLE"; + case PSA_SUCCESS: + return "PSA_SUCCESS"; default: return "Error value not recognized"; } @@ -143,6 +152,98 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation) return PSA_ERROR_NOT_SUPPORTED; } +/** + * @brief aead encrypt and decrypt function + * + * See @ref psa_aead_encrypt(...) + * See @ref psa_aead_decrypt(...) + * + * @param direction Whether to encrypt or decrypt, see @ref psa_encrypt_or_decrypt_t + * @return @ref psa_status_t + */ +static psa_status_t psa_aead_encrypt_decrypt( psa_key_id_t key, + psa_algorithm_t alg, + const uint8_t * nonce, + size_t nonce_length, + const uint8_t * additional_data, + size_t additional_data_length, + const uint8_t * input, + size_t input_length, + uint8_t * output, + size_t output_size, + size_t * output_length, + psa_encrypt_or_decrypt_t direction) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + if (!lib_initialized) { + return PSA_ERROR_BAD_STATE; + } + + if ((additional_data_length != 0 && !additional_data) || !nonce) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg) != PSA_ALG_CCM) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (!PSA_ALG_IS_AEAD(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce_length > PSA_AEAD_NONCE_MAX_SIZE) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (direction == PSA_CRYPTO_DRIVER_DECRYPT && (!input || input_length == 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (direction == PSA_CRYPTO_DRIVER_ENCRYPT && (!output || output_size == 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_key_usage_t usage = (direction == PSA_CRYPTO_DRIVER_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT); + + status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); + if (status != PSA_SUCCESS) { + unlock_status = psa_unlock_key_slot(slot); + if (unlock_status != PSA_SUCCESS) { + status = unlock_status; + } + return status; + } + + if (direction == PSA_CRYPTO_DRIVER_ENCRYPT) { + if (output_size < PSA_AEAD_ENCRYPT_OUTPUT_SIZE(slot->attr.type, alg, input_length)) { + unlock_status = psa_unlock_key_slot(slot); + return PSA_ERROR_BUFFER_TOO_SMALL; + } + status = psa_location_dispatch_aead_encrypt(&slot->attr, alg, slot, nonce, nonce_length, + additional_data, additional_data_length, + input, input_length, output, + output_size, output_length); + } + else { + if (output_size < PSA_AEAD_DECRYPT_OUTPUT_SIZE(slot->attr.type, alg, input_length)) { + unlock_status = psa_unlock_key_slot(slot); + return PSA_ERROR_BUFFER_TOO_SMALL; + } + status = psa_location_dispatch_aead_decrypt(&slot->attr, alg, slot, nonce, nonce_length, + additional_data, additional_data_length, + input, input_length, output, + output_size, output_length); + } + + unlock_status = psa_unlock_key_slot(slot); + return ((status == PSA_SUCCESS) ? unlock_status : status); +} + psa_status_t psa_aead_decrypt( psa_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce, @@ -155,18 +256,10 @@ psa_status_t psa_aead_decrypt( psa_key_id_t key, size_t plaintext_size, size_t *plaintext_length) { - (void)key; - (void)alg; - (void)nonce; - (void)nonce_length; - (void)additional_data; - (void)additional_data_length; - (void)ciphertext; - (void)ciphertext_length; - (void)plaintext; - (void)plaintext_size; - (void)plaintext_length; - return PSA_ERROR_NOT_SUPPORTED; + return psa_aead_encrypt_decrypt(key, alg, nonce, nonce_length, additional_data, + additional_data_length, ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length, + PSA_CRYPTO_DRIVER_DECRYPT); } psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, @@ -191,18 +284,10 @@ psa_status_t psa_aead_encrypt( psa_key_id_t key, size_t ciphertext_size, size_t *ciphertext_length) { - (void)key; - (void)alg; - (void)nonce; - (void)nonce_length; - (void)additional_data; - (void)additional_data_length; - (void)plaintext; - (void)plaintext_length; - (void)ciphertext; - (void)ciphertext_size; - (void)ciphertext_length; - return PSA_ERROR_NOT_SUPPORTED; + return psa_aead_encrypt_decrypt(key, alg, nonce, nonce_length, additional_data, + additional_data_length, plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length, + PSA_CRYPTO_DRIVER_ENCRYPT); } psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, diff --git a/sys/psa_crypto/psa_crypto_algorithm_dispatch.c b/sys/psa_crypto/psa_crypto_algorithm_dispatch.c index b1cf750362..71935d9a83 100644 --- a/sys/psa_crypto/psa_crypto_algorithm_dispatch.c +++ b/sys/psa_crypto/psa_crypto_algorithm_dispatch.c @@ -38,6 +38,10 @@ #include "psa_ciphers.h" #endif +#if IS_USED(MODULE_PSA_AEAD) +#include "psa_aead.h" +#endif + #if IS_USED(MODULE_PSA_KEY_MANAGEMENT) #include "psa_crypto_operation_encoder.h" #endif @@ -729,6 +733,152 @@ psa_status_t psa_algorithm_dispatch_cipher_decrypt( const psa_key_attributes_t * } #endif /* MODULE_PSA_CIPHER */ +#if IS_USED(MODULE_PSA_AEAD) +psa_status_t psa_algorithm_dispatch_aead_encrypt( const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length) +{ + psa_aead_op_t op = PSA_ENCODE_AEAD_OPERATION(alg, attributes->type, attributes->bits); + + uint8_t *key_data = NULL; + size_t *key_bytes = NULL; + + psa_get_key_data_from_key_slot(slot, &key_data, &key_bytes); + + if (attributes->type != PSA_KEY_TYPE_AES) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (op == PSA_INVALID_OPERATION) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint8_t tag_len = PSA_AEAD_TAG_LENGTH(attributes->type, attributes->bits, alg); + + switch (op) { + #if IS_USED(MODULE_PSA_AEAD_AES_128_CCM) + case PSA_CCM_AES_128: + return psa_aead_aes_128_ccm_encrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, plaintext, + plaintext_length, ciphertext, + ciphertext_size, ciphertext_length); + #endif + #if IS_USED(MODULE_PSA_AEAD_AES_192_CCM) + case PSA_CCM_AES_192: + return psa_aead_aes_192_ccm_encrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, plaintext, + plaintext_length, ciphertext, + ciphertext_size, ciphertext_length); + #endif + #if IS_USED(MODULE_PSA_AEAD_AES_256_CCM) + case PSA_CCM_AES_256: + return psa_aead_aes_256_ccm_encrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, plaintext, + plaintext_length, ciphertext, + ciphertext_size, ciphertext_length); + #endif + default: + (void)attributes; + (void)alg; + (void)slot; + (void)nonce; + (void)nonce_length; + (void)additional_data; + (void)additional_data_length; + (void)plaintext; + (void)plaintext_length; + (void)ciphertext; + (void)ciphertext_size; + (void)ciphertext_length; + return PSA_ERROR_NOT_SUPPORTED; + } +} + +psa_status_t psa_algorithm_dispatch_aead_decrypt( const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length) +{ + psa_aead_op_t op = PSA_ENCODE_AEAD_OPERATION(alg, attributes->type, attributes->bits); + + uint8_t *key_data = NULL; + size_t *key_bytes = NULL; + + psa_get_key_data_from_key_slot(slot, &key_data, &key_bytes); + + if (attributes->type != PSA_KEY_TYPE_AES) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (op == PSA_INVALID_OPERATION) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + uint8_t tag_len = PSA_AEAD_TAG_LENGTH(attributes->type, attributes->bits, alg); + + switch (op) { + #if IS_USED(MODULE_PSA_AEAD_AES_128_CCM) + case PSA_CCM_AES_128: + return psa_aead_aes_128_ccm_decrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, ciphertext, + ciphertext_length, plaintext, + plaintext_size, plaintext_length); + #endif + #if IS_USED(MODULE_PSA_AEAD_AES_192_CCM) + case PSA_CCM_AES_192: + return psa_aead_aes_192_ccm_decrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, ciphertext, + ciphertext_length, plaintext, + plaintext_size, plaintext_length); + #endif + #if IS_USED(MODULE_PSA_AEAD_AES_256_CCM) + case PSA_CCM_AES_256: + return psa_aead_aes_256_ccm_decrypt(attributes, key_data, *key_bytes, tag_len, + nonce, nonce_length, additional_data, + additional_data_length, ciphertext, + ciphertext_length, plaintext, + plaintext_size, plaintext_length); + #endif + default: + (void)attributes; + (void)alg; + (void)slot; + (void)nonce; + (void)nonce_length; + (void)additional_data; + (void)additional_data_length; + (void)ciphertext; + (void)ciphertext_length; + (void)plaintext; + (void)plaintext_size; + (void)plaintext_length; + return PSA_ERROR_NOT_SUPPORTED; + } +} +#endif /* MODULE_PSA_AEAD */ + #if IS_USED(MODULE_PSA_MAC) psa_status_t psa_algorithm_dispatch_mac_compute(const psa_key_attributes_t *attributes, psa_algorithm_t alg, diff --git a/sys/psa_crypto/psa_crypto_location_dispatch.c b/sys/psa_crypto/psa_crypto_location_dispatch.c index fabce67a1a..c762c2340d 100644 --- a/sys/psa_crypto/psa_crypto_location_dispatch.c +++ b/sys/psa_crypto/psa_crypto_location_dispatch.c @@ -329,6 +329,52 @@ psa_status_t psa_location_dispatch_cipher_decrypt( const psa_key_attributes_t * #endif /* MODULE_PSA_CIPHER */ +#if IS_USED(MODULE_PSA_AEAD) +psa_status_t psa_location_dispatch_aead_encrypt(const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length) +{ + + /* TODO: implement MODULE_PSA_SECURE_ELEMENT support */ + + return psa_algorithm_dispatch_aead_encrypt(attributes, alg, slot, nonce, + nonce_length, additional_data, + additional_data_length, plaintext, + plaintext_length, ciphertext, + ciphertext_size, ciphertext_length); +} + +psa_status_t psa_location_dispatch_aead_decrypt(const psa_key_attributes_t *attributes, + psa_algorithm_t alg, + const psa_key_slot_t *slot, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length) +{ + /* TODO: implement MODULE_PSA_SECURE_ELEMENT support */ + + return psa_algorithm_dispatch_aead_decrypt( attributes, alg, slot, nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, plaintext, + plaintext_size, plaintext_length); +} +#endif /* MODULE_PSA_AEAD */ + #if IS_USED(MODULE_PSA_ASYMMETRIC) psa_status_t psa_location_dispatch_sign_hash( const psa_key_attributes_t *attributes, psa_algorithm_t alg,