diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index bf89174d1d..f753f23173 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -388,6 +388,11 @@ PSEUDOMODULES += posix_headers PSEUDOMODULES += printf_float PSEUDOMODULES += prng PSEUDOMODULES += prng_% +PSEUDOMODULES += psa_riot_cipher_aes_common +PSEUDOMODULES += psa_riot_cipher_aes_128_ecb +PSEUDOMODULES += psa_riot_cipher_aes_128_cbc +PSEUDOMODULES += psa_riot_cipher_aes_192_cbc +PSEUDOMODULES += psa_riot_cipher_aes_256_cbc PSEUDOMODULES += fortuna_reseed ## @defgroup pseudomodule_random_cmd random_cmd ## @ingroup sys_shell_commands diff --git a/sys/crypto/Kconfig b/sys/crypto/Kconfig index 9311436a8a..b22afcd729 100644 --- a/sys/crypto/Kconfig +++ b/sys/crypto/Kconfig @@ -33,6 +33,7 @@ config MODULE_CRYPTO_AES_UNROLL endmenu # Crypto AES options +rsource "psa_riot_cipher/Kconfig" rsource "modes/Kconfig" endif # Crypto diff --git a/sys/crypto/Makefile b/sys/crypto/Makefile index 9e7ab5fd30..7ff0741848 100644 --- a/sys/crypto/Makefile +++ b/sys/crypto/Makefile @@ -4,4 +4,8 @@ endif CFLAGS += -DRIOT_CHACHA_PRNG_DEFAULT="$(RIOT_CHACHA_PRNG_DEFAULT)" +ifneq (,$(filter psa_riot_cipher_%,$(USEMODULE))) + DIRS += psa_riot_cipher +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/crypto/psa_riot_cipher/Kconfig b/sys/crypto/psa_riot_cipher/Kconfig new file mode 100644 index 0000000000..a57a94f160 --- /dev/null +++ b/sys/crypto/psa_riot_cipher/Kconfig @@ -0,0 +1,38 @@ +# 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. +# + +config MODULE_PSA_RIOT_CIPHER_AES_128_ECB + bool + depends on MODULE_PSA_CRYPTO + select MODULE_CRYPTO_AES_128 + select MODULE_PSA_RIOT_CIPHER + +config MODULE_PSA_RIOT_CIPHER_AES_128_CBC + bool + depends on MODULE_PSA_CRYPTO + select MODULE_CRYPTO_AES_128 + select MODULE_PSA_RIOT_CIPHER + +config MODULE_PSA_RIOT_CIPHER_AES_192_CBC + bool + depends on MODULE_PSA_CRYPTO + select MODULE_CRYPTO_AES_192 + select MODULE_PSA_RIOT_CIPHER + +config MODULE_PSA_RIOT_CIPHER_AES_256_CBC + bool + depends on MODULE_PSA_CRYPTO + select MODULE_CRYPTO_AES_192 + select MODULE_PSA_RIOT_CIPHER + +config MODULE_PSA_RIOT_CIPHER + bool + select MODULE_PSA_RIOT_CIPHER_AES_COMMON + select MODULE_CIPHER_MODES + +config MODULE_PSA_RIOT_CIPHER_AES_COMMON + bool diff --git a/sys/crypto/psa_riot_cipher/Makefile b/sys/crypto/psa_riot_cipher/Makefile new file mode 100644 index 0000000000..aacc8d4aaf --- /dev/null +++ b/sys/crypto/psa_riot_cipher/Makefile @@ -0,0 +1,4 @@ +BASE_MODULE := psa_riot_cipher +SUBMODULES := 1 + +include $(RIOTBASE)/Makefile.base diff --git a/sys/crypto/psa_riot_cipher/aes_128_cbc.c b/sys/crypto/psa_riot_cipher/aes_128_cbc.c new file mode 100644 index 0000000000..09cf654322 --- /dev/null +++ b/sys/crypto/psa_riot_cipher/aes_128_cbc.c @@ -0,0 +1,91 @@ +/* + * 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 + * @brief Glue code translating between PSA Crypto and the RIOT Cipher module + * + * @author Lena Boeckmann + * + * @} + */ + +#include "psa/crypto.h" +#include "crypto/modes/cbc.h" +#include "aes_common.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +psa_status_t psa_cipher_cbc_aes_128_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + DEBUG("RIOT AES 128 Cipher"); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t operation = psa_cipher_operation_init(); + size_t iv_length = 0; + size_t required_output_buf_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(PSA_KEY_TYPE_AES, + PSA_ALG_CBC_NO_PADDING, input_length); + + if (output_size < required_output_buf_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + operation.iv_required = 1; + operation.default_iv_length = PSA_CIPHER_IV_LENGTH(attributes->type, alg); + *output_length = 0; + + status = psa_cipher_generate_iv(&operation, output, operation.default_iv_length, &iv_length); + if (status != PSA_SUCCESS) { + return status; + } + + return cbc_aes_common_encrypt_decrypt(&operation.backend_ctx.cipher_ctx.aes_128, key_buffer, + key_buffer_size, output, input, input_length, + output + iv_length, output_length, PSA_CRYPTO_DRIVER_ENCRYPT); +} + +psa_status_t psa_cipher_cbc_aes_128_decrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + DEBUG("RIOT AES 128 Cipher"); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t operation = psa_cipher_operation_init(); + size_t required_output_buf_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE(PSA_KEY_TYPE_AES, + PSA_ALG_CBC_NO_PADDING, input_length); + + if (output_size < required_output_buf_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + operation.iv_required = 1; + operation.default_iv_length = PSA_CIPHER_IV_LENGTH(attributes->type, alg); + *output_length = 0; + + return cbc_aes_common_encrypt_decrypt(&operation.backend_ctx.cipher_ctx.aes_128, key_buffer, + key_buffer_size, input, input + operation.default_iv_length, + input_length - operation.default_iv_length, output, + output_length, PSA_CRYPTO_DRIVER_DECRYPT); +} diff --git a/sys/crypto/psa_riot_cipher/aes_256_cbc.c b/sys/crypto/psa_riot_cipher/aes_256_cbc.c new file mode 100644 index 0000000000..66c1a9bcd8 --- /dev/null +++ b/sys/crypto/psa_riot_cipher/aes_256_cbc.c @@ -0,0 +1,61 @@ +/* + * 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 + * @brief Glue code translating between PSA Crypto and the RIOT Cipher module + * + * @author Lena Boeckmann + * + * @} + */ + +#include "psa/crypto.h" +#include "crypto/modes/cbc.h" +#include "aes_common.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +psa_status_t psa_cipher_cbc_aes_256_encrypt(const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + DEBUG("RIOT AES 256 Cipher"); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_cipher_operation_t operation = psa_cipher_operation_init(); + size_t iv_length = 0; + size_t required_output_buf_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(PSA_KEY_TYPE_AES, + PSA_ALG_CBC_NO_PADDING, input_length); + + if (output_size < required_output_buf_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + operation.iv_required = 1; + operation.default_iv_length = PSA_CIPHER_IV_LENGTH(attributes->type, alg); + *output_length = 0; + + status = psa_cipher_generate_iv(&operation, output, operation.default_iv_length, &iv_length); + if (status != PSA_SUCCESS) { + return status; + } + status = cbc_aes_common(&operation.backend_ctx.cipher_ctx.aes_256, key_buffer, key_buffer_size, + output, input, input_length, output + operation.default_iv_length, + output_length); + return status; +} diff --git a/sys/crypto/psa_riot_cipher/aes_common.c b/sys/crypto/psa_riot_cipher/aes_common.c new file mode 100644 index 0000000000..48e86ad435 --- /dev/null +++ b/sys/crypto/psa_riot_cipher/aes_common.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 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 + * @brief Glue code translating between PSA Crypto and the RIOT Cipher module + * + * @author Lena Boeckmann + * + * @} + */ + +#include "psa/crypto.h" +#include "crypto/modes/cbc.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +psa_status_t cipher_to_psa_error(int error) +{ + switch (error) { + case CIPHER_ERR_INVALID_KEY_SIZE: + case CIPHER_ERR_INVALID_LENGTH: + case CIPHER_ERR_BAD_CONTEXT_SIZE: + return PSA_ERROR_INVALID_ARGUMENT; + default: + return PSA_ERROR_GENERIC_ERROR; + } +} + +psa_status_t cbc_aes_common_encrypt_decrypt(cipher_t *ctx, + const uint8_t *key_buffer, + size_t key_buffer_size, + const uint8_t *iv, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length, + psa_encrypt_or_decrypt_t direction) +{ + int ret = 0; + + ret = cipher_init(ctx, CIPHER_AES, key_buffer, key_buffer_size); + if (ret != CIPHER_INIT_SUCCESS) { + return cipher_to_psa_error(ret); + } + + if (direction == PSA_CRYPTO_DRIVER_ENCRYPT) { + ret = cipher_encrypt_cbc(ctx, (uint8_t *)iv, input, input_length, output); + } + else { + ret = cipher_decrypt_cbc(ctx, (uint8_t *)iv, input, input_length, output); + } + if (ret <= 0) { + return cipher_to_psa_error(ret); + } + + *output_length = ret; + return PSA_SUCCESS; +} diff --git a/sys/crypto/psa_riot_cipher/aes_common.h b/sys/crypto/psa_riot_cipher/aes_common.h new file mode 100644 index 0000000000..d70041bb01 --- /dev/null +++ b/sys/crypto/psa_riot_cipher/aes_common.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 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. + */ + +/** + * @cond + * @ingroup sys_crypto + * @{ + * + * @brief Glue code translating between PSA Crypto and the RIOT Cipher module + * + * @author Lena Boeckmann + * + */ + +#ifndef AES_COMMON_H +#define AES_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/crypto.h" +#include "crypto/modes/cbc.h" + +/** + * @brief Converts errors of the RIOT cipher module to PSA status values + * + * @param error + * @return @ref psa_status_t + */ +psa_status_t cipher_to_psa_error(int error); + +/** + * @brief Common AES CBC Encrypt function + * + * @return @ref psa_status_t + */ +psa_status_t cbc_aes_common_encrypt_decrypt(cipher_t *ctx, + const uint8_t *key_buffer, + size_t key_buffer_size, + const uint8_t *iv, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length, + psa_encrypt_or_decrypt_t direction); + +#ifdef __cplusplus +} +#endif + +#endif /* AES_COMMON_H */ +/** @} */ +/** @endcond */ diff --git a/sys/include/crypto/psa/riot_ciphers.h b/sys/include/crypto/psa/riot_ciphers.h new file mode 100644 index 0000000000..433be055fa --- /dev/null +++ b/sys/include/crypto/psa/riot_ciphers.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 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 + * @{ + * + * @brief Contexts for the RIOT cipher module + * + * @author Lena Boeckmann + * + */ + +#ifndef CRYPTO_PSA_RIOT_CIPHERS_H +#define CRYPTO_PSA_RIOT_CIPHERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "crypto/ciphers.h" +#include "kernel_defines.h" + +#if IS_USED(MODULE_PSA_RIOT_CIPHER_AES_128_CBC) +typedef cipher_t psa_cipher_aes_128_ctx_t; +#endif +#if IS_USED(MODULE_PSA_RIOT_CIPHER_AES_192_CBC) +typedef cipher_t psa_cipher_aes_192_ctx_t; +#endif +#if IS_USED(MODULE_PSA_RIOT_CIPHER_AES_256_CBC) +typedef cipher_t psa_cipher_aes_256_ctx_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTO_PSA_RIOT_CIPHERS_H */ +/** @} */