mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/psa_crypto: implement persistent key storage
This commit is contained in:
parent
a9e7b441a7
commit
cbadc4f658
@ -1503,6 +1503,10 @@ psa_status_t psa_copy_key(psa_key_id_t source_key,
|
||||
* If a key is currently in use in a multi-part operation, then destroying the key will
|
||||
* cause the multi-part operation to fail.
|
||||
*
|
||||
* @warning This implementation uses a virtual file system for storing and reading persistent keys
|
||||
* to and from flash. Destroying a key only unlinks the file and does not erase the actual
|
||||
* key data from flash. Anyone with hardware access can still recover the key material.
|
||||
*
|
||||
* @param key Identifier of the key to erase. If this is @ref PSA_KEY_ID_NULL, do nothing and
|
||||
* return @ref PSA_SUCCESS.
|
||||
*
|
||||
|
@ -8,6 +8,10 @@ ifneq (,$(filter psa_key_slot_mgmt,$(USEMODULE)))
|
||||
DIRS += psa_key_slot_mgmt
|
||||
endif
|
||||
|
||||
ifneq (,$(filter psa_persistent_storage,$(USEMODULE)))
|
||||
DIRS += psa_persistent_storage
|
||||
endif
|
||||
|
||||
ifneq (,$(filter psa_se_mgmt,$(USEMODULE)))
|
||||
DIRS += psa_se_mgmt
|
||||
endif
|
||||
|
@ -3,6 +3,15 @@ ifneq (,$(filter psa_crypto,$(USEMODULE)))
|
||||
USEMODULE += prng_sha256prng
|
||||
endif
|
||||
|
||||
ifneq (,$(filter psa_persistent_storage, $(USEMODULE)))
|
||||
USEPKG += nanocbor
|
||||
USEPKG += littlefs2
|
||||
USEMODULE += vfs
|
||||
USEMODULE += vfs_default
|
||||
USEMODULE += vfs_auto_format
|
||||
USEMODULE += vfs_auto_mount
|
||||
endif
|
||||
|
||||
# Asymmetric
|
||||
ifneq (,$(filter psa_asymmetric,$(USEMODULE)))
|
||||
USEMODULE += psa_key_management
|
||||
|
@ -112,8 +112,13 @@
|
||||
* Persistent keys will also be written into flash memory for later access. To destroy
|
||||
* them they must be explicitly deleted with the `psa_destroy_key()` function.
|
||||
*
|
||||
* @note So far this implementation only supports volatile storage. Persistent storage
|
||||
* will be added in the future.
|
||||
* @note Persistent key storage can be optionally enabled on `native` and on the `nRF52840dk`.
|
||||
* For this, add `USEMODULE += psa_persistent_storage` to your application makefile
|
||||
* or `CONFIG_MODULE_PSA_PERSISTENT_STORAGE=y` to your `app.config.test` file.
|
||||
* Example: `tests/sys/psa_crypto_persistent_storage`
|
||||
*
|
||||
* @warning Be aware that the current implementation writes keys in plain text to flash memory.
|
||||
* Anyone with hardware access can read them.
|
||||
*
|
||||
* #### Lifetime Encoding
|
||||
* When creating a key, the user needs to specify a lifetime value, which actually consists
|
||||
@ -220,6 +225,11 @@
|
||||
* CFLAGS += -DCONFIG_PSA_PROTECTED_KEY_COUNT=2
|
||||
* @endcode
|
||||
*
|
||||
* @note The key slot count defines the maximum number of keys that can be cached in
|
||||
* RAM at runtime. It does not limit the number of persistent keys that can be stored
|
||||
* in flash memory. It is the user's responsibility to keep track of the number of
|
||||
* persistently stored keys.
|
||||
*
|
||||
* ## Available Modules {#available-modules}
|
||||
* Below are the currently available modules.
|
||||
* No matter which operation you need, you always have to choose the base module.
|
||||
@ -233,6 +243,9 @@
|
||||
* When using `app.config.test` files in your application directory, you need to write the
|
||||
* names in uppercase and add the prefix `CONFIG_MODULE_` to all of them.
|
||||
*
|
||||
* ### Key Storage
|
||||
* - Persistent Key Storage: psa_persistent_storage
|
||||
*
|
||||
* ### Asymmetric Crypto
|
||||
* - Base: psa_asymmetric
|
||||
*
|
||||
|
149
sys/psa_crypto/include/psa_crypto_cbor_encoder.h
Normal file
149
sys/psa_crypto/include/psa_crypto_cbor_encoder.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
* @defgroup sys_psa_crypto_cbor_encoder Module for encoding PSA keys in CBOR
|
||||
* @{
|
||||
*
|
||||
* @file psa_crypto_cbor_encoder.h
|
||||
* @brief
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_CBOR_ENCODER_H
|
||||
#define PSA_CRYPTO_CBOR_ENCODER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "psa_crypto_slot_management.h"
|
||||
|
||||
/**
|
||||
* @brief Required size of CBOR output buffer from start to end of attributes.
|
||||
* Adds attributes sizes to CBOR encodings for individual values.
|
||||
*/
|
||||
#define CBOR_BUF_SIZE_START ( 1 + /* Array encoding */ \
|
||||
1 + /* Array encoding */ \
|
||||
1 + sizeof(psa_key_id_t) + \
|
||||
1 + sizeof(psa_key_type_t) + \
|
||||
1 + sizeof(psa_key_bits_t) + \
|
||||
1 + sizeof(psa_key_lifetime_t) + \
|
||||
1 + /* Array encoding */ \
|
||||
1 + sizeof(psa_key_usage_t) + \
|
||||
1 + sizeof(psa_algorithm_t) \
|
||||
)
|
||||
|
||||
#if PSA_SINGLE_KEY_COUNT
|
||||
/**
|
||||
* @brief Required CBOR buffer size to encode a basic PSA key slot containing
|
||||
* a single key.
|
||||
*/
|
||||
#define CBOR_BUF_SIZE_SINGLE_KEY ( CBOR_BUF_SIZE_START + \
|
||||
3 + /* Bytestring encoding and size */ \
|
||||
PSA_MAX_KEY_DATA_SIZE \
|
||||
)
|
||||
#endif /* PSA_SINGLE_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
/**
|
||||
* @brief Required CBOR buffer size to encode a basic PSA key slot containing
|
||||
* an asymmetric key pair.
|
||||
*/
|
||||
#define CBOR_BUF_SIZE_KEY_PAIR ( CBOR_BUF_SIZE_START + \
|
||||
1 + \
|
||||
3 + PSA_BITS_TO_BYTES(PSA_MAX_PRIV_KEY_SIZE) + \
|
||||
3 + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
|
||||
)
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT && IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
/**
|
||||
* @brief Required CBOR buffer size to encode a basic PSA key slot containing
|
||||
* a key in protected memory.
|
||||
*/
|
||||
#define CBOR_BUF_SIZE_PROT_KEY ( CBOR_BUF_SIZE_START + \
|
||||
1 + \
|
||||
1 + sizeof(psa_key_slot_number_t) + \
|
||||
3 + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
|
||||
)
|
||||
#elif PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Required CBOR buffer size to encode a basic PSA key slot containing
|
||||
* a key in protected memory.
|
||||
*/
|
||||
#define CBOR_BUF_SIZE_PROT_KEY ( CBOR_BUF_SIZE_START + \
|
||||
1 + \
|
||||
1 + sizeof(psa_key_slot_number_t) \
|
||||
)
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
/**
|
||||
* @brief Encodes a basic key slot in CBOR
|
||||
*
|
||||
* Single Key Format:
|
||||
* - [
|
||||
* [ID, Type, Bits, Lifetime, [Usage, Algorithm]],
|
||||
* h'key
|
||||
* ]
|
||||
*
|
||||
* Asymmetric Key Pair Format:
|
||||
* - [
|
||||
* [ID, Type, Bits, Lifetime, [Usage, Algorithm]],
|
||||
* [h'private_key, h'public_key]
|
||||
* ]
|
||||
*
|
||||
* Protected Key Format:
|
||||
* - [
|
||||
* [ID, Type, Bits, Lifetime, [Usage, Algorithm]],
|
||||
* [Slot No, *optional: h'public_key*]
|
||||
* ]
|
||||
*
|
||||
* @param[in] slot Pointer to slot containing the key to encode
|
||||
* @param[in] output Buffer to write the encoded key to
|
||||
* @param[in] output_len Length of output buffer
|
||||
* @param[out] output_size Pointer to write actual length of encoding
|
||||
*
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_encode_key_slot(psa_key_slot_t *slot, uint8_t *output,
|
||||
size_t output_len, size_t *output_size);
|
||||
|
||||
/**
|
||||
* @brief Decode CBOR encoded key data and write to PSA key slot. Only decodes the key and should
|
||||
* be called in combination with psa_decode_key_attributes.
|
||||
*
|
||||
* @param slot Pointer to key slot to write decoded key to
|
||||
* @param cbor_buf Buffer containing CBOR encoded data
|
||||
* @param cbor_buf_size Size of @p cbor_buf
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_decode_key_slot_data(psa_key_slot_t *slot, uint8_t *cbor_buf,
|
||||
size_t cbor_buf_size);
|
||||
|
||||
/**
|
||||
* @brief Decode CBOR PSA key attributes. Only decodes key attributes and not the actual key.
|
||||
* Key can be decoded with psa_decode_key_slot_data.
|
||||
*
|
||||
* @param attr Key attribute struct to store decoded attributes
|
||||
* @param cbor_buf Buffer containing CBOR encoded data
|
||||
* @param cbor_buf_size Size of @p cbor_buf
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_decode_key_attributes(psa_key_attributes_t *attr, uint8_t *cbor_buf,
|
||||
size_t cbor_buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PSA_CRYPTO_CBOR_ENCODER_H */
|
||||
/** @} */
|
73
sys/psa_crypto/include/psa_crypto_persistent_storage.h
Normal file
73
sys/psa_crypto/include/psa_crypto_persistent_storage.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
* @defgroup sys_psa_crypto_pers_stor PSA Crypto Persistent Storage API
|
||||
* @{
|
||||
*
|
||||
* @file psa_crypto_persistent_storage.h
|
||||
* @brief
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_PERSISTENT_STORAGE_H
|
||||
#define PSA_CRYPTO_PERSISTENT_STORAGE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "psa/crypto.h"
|
||||
|
||||
/**
|
||||
* @brief Writes a CBOR encoded key slot to a file
|
||||
*
|
||||
* @param id ID of slot, used as filename
|
||||
* @param input Pointer to CBOR encoded data
|
||||
* @param input_len Length of CBOR encoded data
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_write_encoded_key_slot_to_file(psa_key_id_t id,
|
||||
uint8_t* input,
|
||||
size_t input_len);
|
||||
|
||||
/**
|
||||
* @brief Reads a CBOR encoded key slot from a file
|
||||
*
|
||||
* @param id ID of the desired key
|
||||
* @param output Output buffer to write CBOR data to
|
||||
* @param output_size Size of output buffer
|
||||
* @param output_data_len Actual length of CBOR encoded data
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_read_encoded_key_slot_from_file(psa_key_id_t id,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_data_len);
|
||||
|
||||
/**
|
||||
* @brief Destroy a key in persistent storage
|
||||
*
|
||||
* @note This will only remove the link to the key file without erasing the
|
||||
* key from the flash. The key material can still be recovered by someone
|
||||
* with access to the hardware.
|
||||
*
|
||||
* @param key_id ID of the key to be destroyed
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_destroy_persistent_key(psa_key_id_t key_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PSA_CRYPTO_PERSISTENT_STORAGE_H */
|
||||
/** @} */
|
@ -86,6 +86,51 @@ typedef struct {
|
||||
#endif /* PSA_SINGLE_KEY_COUNT */
|
||||
} psa_key_slot_t;
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Structure for a protected key slot.
|
||||
*
|
||||
* These slots hold Slot Numbers for keys in protected storage and, if the key type is an
|
||||
* asymmetric key pair, the public key.
|
||||
*/
|
||||
typedef struct {
|
||||
clist_node_t node;
|
||||
size_t lock_count;
|
||||
psa_key_attributes_t attr;
|
||||
struct prot_key_data {
|
||||
psa_key_slot_number_t slot_number;
|
||||
#if IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
uint8_t pubkey_data[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
|
||||
size_t pubkey_data_len;
|
||||
#endif
|
||||
} key;
|
||||
} psa_prot_key_slot_t;
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
/**
|
||||
* @brief Structure for asymmetric key pairs.
|
||||
*
|
||||
* Contains asymmetric private and public key pairs.
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
clist_node_t node;
|
||||
size_t lock_count;
|
||||
psa_key_attributes_t attr;
|
||||
struct key_pair_data {
|
||||
/** Contains asymmetric private key*/
|
||||
uint8_t privkey_data[PSA_BITS_TO_BYTES(PSA_MAX_PRIV_KEY_SIZE)];
|
||||
/** Contains actual size of asymmetric private key */
|
||||
size_t privkey_data_len;
|
||||
/** Contains asymmetric public key */
|
||||
uint8_t pubkey_data[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
|
||||
/*!< Contains actual size of asymmetric private key */
|
||||
size_t pubkey_data_len;
|
||||
} key;
|
||||
} psa_key_pair_slot_t;
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
/**
|
||||
* @brief Initializes the allocated key slots and prepares the internal key slot lists.
|
||||
*/
|
||||
@ -165,6 +210,14 @@ void psa_wipe_all_key_slots(void);
|
||||
*/
|
||||
psa_status_t psa_get_and_lock_key_slot(psa_key_id_t id, psa_key_slot_t **slot);
|
||||
|
||||
/**
|
||||
* @brief Store a key slot in persistent storage
|
||||
*
|
||||
* @param slot Pointer to slot to store in persistent storage
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t psa_persist_key_slot_in_storage(psa_key_slot_t *slot);
|
||||
|
||||
/**
|
||||
* @brief Find a currently empty key slot that is appropriate for the key.
|
||||
*
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "psa_crypto_location_dispatch.h"
|
||||
#include "psa_crypto_algorithm_dispatch.h"
|
||||
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
#include "psa_crypto_persistent_storage.h"
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
#include "random.h"
|
||||
#include "kernel_defines.h"
|
||||
|
||||
@ -394,10 +398,10 @@ static psa_status_t psa_key_policy_permits( const psa_key_policy_t *policy,
|
||||
* @ref PSA_ERROR_NOT_SUPPORTED
|
||||
* @ref PSA_ERROR_CORRUPTION_DETECTED
|
||||
*/
|
||||
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)
|
||||
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)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
@ -1080,11 +1084,13 @@ static psa_status_t psa_validate_key_attributes(const psa_key_attributes_t *attr
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
else {
|
||||
if (!psa_is_valid_key_id(key, 0)) {
|
||||
if (!psa_is_valid_key_id(key, 1)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
status = psa_validate_key_policy(&attributes->policy);
|
||||
if (status != PSA_SUCCESS) {
|
||||
@ -1152,29 +1158,27 @@ static psa_status_t psa_start_key_creation(psa_key_creation_method_t method,
|
||||
*
|
||||
* @param slot Pointer to slot that the key is stored in
|
||||
* @param driver SE driver, in case the key creation took place on a secure element
|
||||
* @param key Pointer which will contain the key ID assigned to the key
|
||||
* @param key_id Pointer which will contain the key ID assigned to the key
|
||||
*
|
||||
* @return @ref psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_finish_key_creation(psa_key_slot_t *slot, psa_se_drv_data_t *driver,
|
||||
psa_key_id_t *key)
|
||||
psa_key_id_t *key_id)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
|
||||
*key = PSA_KEY_ID_NULL;
|
||||
/* TODO: Finish persistent key storage */
|
||||
/* TODO: Finish SE key storage with transaction */
|
||||
|
||||
if (status == PSA_SUCCESS) {
|
||||
*key = slot->attr.id;
|
||||
status = psa_unlock_key_slot(slot);
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
|
||||
*key_id = slot->attr.id;
|
||||
}
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
else {
|
||||
(void)slot;
|
||||
status = psa_persist_key_slot_in_storage(slot);
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
(void)driver;
|
||||
return status;
|
||||
psa_status_t unlock_status = psa_unlock_key_slot(slot);
|
||||
return ((status == PSA_SUCCESS) ? unlock_status : status);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1217,6 +1221,17 @@ psa_status_t psa_destroy_key(psa_key_id_t key)
|
||||
return PSA_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
|
||||
status = psa_destroy_persistent_key(key);
|
||||
if (status != PSA_SUCCESS) {
|
||||
DEBUG("PSA destroy key: Persistent key destruction failed: %s\n",
|
||||
psa_status_to_humanly_readable(status));
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
return psa_wipe_key_slot(slot);
|
||||
}
|
||||
|
||||
@ -1351,8 +1366,6 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
|
||||
psa_key_slot_t *slot = NULL;
|
||||
psa_se_drv_data_t *driver = NULL;
|
||||
|
||||
*key = PSA_KEY_ID_NULL;
|
||||
|
||||
if (!lib_initialized) {
|
||||
return PSA_ERROR_BAD_STATE;
|
||||
}
|
||||
@ -1365,6 +1378,10 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {
|
||||
*key = PSA_KEY_ID_NULL;
|
||||
}
|
||||
|
||||
/* Find empty slot */
|
||||
status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, &slot, &driver);
|
||||
if (status != PSA_SUCCESS) {
|
||||
@ -1387,7 +1404,6 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
|
||||
}
|
||||
|
||||
status = psa_finish_key_creation(slot, driver, key);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
psa_fail_key_creation(slot, driver);
|
||||
}
|
||||
@ -1485,7 +1501,9 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
*key = PSA_KEY_ID_NULL;
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {
|
||||
*key = PSA_KEY_ID_NULL;
|
||||
}
|
||||
|
||||
/* Find empty slot */
|
||||
status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, &slot, &driver);
|
||||
|
@ -25,26 +25,29 @@
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Structure for a protected key slot.
|
||||
*
|
||||
* These slots hold Slot Numbers for keys in protected storage and, if the key type is an
|
||||
* asymmetric key pair, the public key.
|
||||
*/
|
||||
typedef struct {
|
||||
clist_node_t node;
|
||||
size_t lock_count;
|
||||
psa_key_attributes_t attr;
|
||||
struct prot_key_data {
|
||||
psa_key_slot_number_t slot_number;
|
||||
#if IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
uint8_t pubkey_data[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
|
||||
size_t pubkey_data_len;
|
||||
#endif
|
||||
} key;
|
||||
} psa_prot_key_slot_t;
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
#include "psa_crypto_persistent_storage.h"
|
||||
#include "psa_crypto_cbor_encoder.h"
|
||||
|
||||
/**
|
||||
* @brief Max size required for the CBOR buffer.
|
||||
*
|
||||
* Depends on the key type and size.
|
||||
*/
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
#define CBOR_BUF_MAX_SIZE (CBOR_BUF_SIZE_KEY_PAIR)
|
||||
#elif PSA_PROTECTED_KEY_COUNT && IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
#define CBOR_BUF_MAX_SIZE (CBOR_BUF_SIZE_PROT_KEY)
|
||||
#elif PSA_SINGLE_KEY_COUNT
|
||||
#define CBOR_BUF_MAX_SIZE (CBOR_BUF_SIZE_SINGLE_KEY)
|
||||
#elif PSA_PROTECTED_KEY_COUNT
|
||||
#define CBOR_BUF_MAX_SIZE (CBOR_BUF_SIZE_PROT_KEY)
|
||||
#else
|
||||
#define CBOR_BUF_MAX_SIZE (0)
|
||||
#endif
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Array containing the protected key slots
|
||||
*/
|
||||
@ -57,28 +60,6 @@ static clist_node_t protected_list_empty;
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
/**
|
||||
* @brief Structure for asymmetric key pairs.
|
||||
*
|
||||
* Contains asymmetric private and public key pairs.
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
clist_node_t node;
|
||||
size_t lock_count;
|
||||
psa_key_attributes_t attr;
|
||||
struct key_pair_data {
|
||||
/** Contains asymmetric private key*/
|
||||
uint8_t privkey_data[PSA_BITS_TO_BYTES(PSA_MAX_PRIV_KEY_SIZE)];
|
||||
/** Contains actual size of asymmetric private key */
|
||||
size_t privkey_data_len;
|
||||
/** Contains asymmetric public key */
|
||||
uint8_t pubkey_data[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
|
||||
/*!< Contains actual size of asymmetric private key */
|
||||
size_t pubkey_data_len;
|
||||
} key;
|
||||
} psa_key_pair_slot_t;
|
||||
|
||||
/**
|
||||
* @brief Array containing the asymmetric key slots
|
||||
*/
|
||||
@ -276,6 +257,19 @@ static int node_id_equals_key_id(clist_node_t *n, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
static int node_lifetime_is_persistent(clist_node_t *n, void *arg)
|
||||
{
|
||||
psa_key_slot_t *slot = container_of(n, psa_key_slot_t, node);
|
||||
if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
(void) arg;
|
||||
return 0;
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
/**
|
||||
* @brief Find the key slot containing the key with a specified ID
|
||||
*
|
||||
@ -291,37 +285,107 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory(psa_key_id_t id, psa_key
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (psa_key_id_is_volatile(id)) {
|
||||
clist_node_t *slot_node = clist_foreach(&key_slot_list, node_id_equals_key_id, &id);
|
||||
if (slot_node == NULL) {
|
||||
return PSA_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
clist_node_t *slot_node = clist_foreach(&key_slot_list, node_id_equals_key_id, &id);
|
||||
if (slot_node == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
|
||||
psa_key_slot_t *slot = container_of(slot_node, psa_key_slot_t, node);
|
||||
status = psa_lock_key_slot(slot);
|
||||
if (status == PSA_SUCCESS) {
|
||||
*p_slot = slot;
|
||||
}
|
||||
psa_key_slot_t *slot = container_of(slot_node, psa_key_slot_t, node);
|
||||
status = psa_lock_key_slot(slot);
|
||||
if (status == PSA_SUCCESS) {
|
||||
*p_slot = slot;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
/**
|
||||
* @brief Reads a persistently stored key from storage
|
||||
*
|
||||
* @param id ID of the desired key
|
||||
* @param p_slot Pointer to store key slot in
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_get_persisted_key_slot_from_storage(psa_key_id_t id,
|
||||
psa_key_slot_t **p_slot)
|
||||
{
|
||||
uint8_t cbor_buf[CBOR_BUF_MAX_SIZE];
|
||||
size_t cbor_encoded_len;
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
|
||||
psa_status_t status = psa_read_encoded_key_slot_from_file(id, cbor_buf, sizeof(cbor_buf), &cbor_encoded_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
/* Decode key attributes first, to get information about key */
|
||||
status = psa_decode_key_attributes(&attr, cbor_buf, cbor_encoded_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Allocate key slot for specific key type */
|
||||
status = psa_allocate_empty_key_slot(&attr.id, &attr, p_slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
(*p_slot)->attr = attr;
|
||||
|
||||
/* Decode rest of key data */
|
||||
return psa_decode_key_slot_data(*p_slot, cbor_buf, cbor_encoded_len);
|
||||
}
|
||||
|
||||
psa_status_t psa_persist_key_slot_in_storage(psa_key_slot_t *slot)
|
||||
{
|
||||
if (psa_key_id_is_volatile(slot->attr.id) ||
|
||||
PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
|
||||
DEBUG("[psa_crypto_slot_mgmt] persist key: ID or lifetime is volatile\n");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
uint8_t cbor_buf[CBOR_BUF_MAX_SIZE];
|
||||
size_t cbor_enc_size;
|
||||
psa_encode_key_slot(slot, cbor_buf, sizeof(cbor_buf), &cbor_enc_size);
|
||||
DEBUG("[psa_crypto_slot_mgmt] Max Key Slot Size: %d | CBOR enc size: %d\n",
|
||||
(int) CBOR_BUF_MAX_SIZE, (int) cbor_enc_size);
|
||||
|
||||
return psa_write_encoded_key_slot_to_file(slot->attr.id, cbor_buf, cbor_enc_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find and wipe a persistent key slot in local storage to make room for a new key
|
||||
*
|
||||
* @return PSA_SUCCESS
|
||||
* @return PSA_ERROR_INSUFFICIENT_STORAGE No persistent key found in local storage
|
||||
* PSA_ERROR_DOES_NOT_EXIST
|
||||
*/
|
||||
static psa_status_t psa_find_and_wipe_persistent_key_from_local_storage(void)
|
||||
{
|
||||
clist_node_t *slot_node = clist_foreach(&key_slot_list, node_lifetime_is_persistent, NULL);
|
||||
if (slot_node == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
|
||||
return psa_wipe_key_slot(container_of(slot_node, psa_key_slot_t, node));
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
psa_status_t psa_get_and_lock_key_slot(psa_key_id_t id, psa_key_slot_t **p_slot)
|
||||
{
|
||||
/* TODO validate ID */
|
||||
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
*p_slot = NULL;
|
||||
|
||||
/* Try to find key in volatile key slot list */
|
||||
status = psa_get_and_lock_key_slot_in_memory(id, p_slot);
|
||||
if (status != PSA_ERROR_DOES_NOT_EXIST) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* TODO: get persistent key from storage and load into slot */
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
if (status == PSA_ERROR_DOES_NOT_EXIST && !psa_key_id_is_volatile(id)) {
|
||||
return psa_get_persisted_key_slot_from_storage(id, p_slot);
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -347,13 +411,20 @@ static psa_status_t psa_allocate_key_slot_in_list(psa_key_slot_t **p_slot,
|
||||
|
||||
/* Check if any empty elements of this key slot type are left */
|
||||
if (clist_is_empty(empty_list)) {
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
/* If no slots left: Look for slot in list with persistent key
|
||||
(key will be stored in persistent memory and slot can be reused) */
|
||||
psa_status_t status = psa_find_and_wipe_persistent_key_from_local_storage();
|
||||
if (status != PSA_SUCCESS) {
|
||||
DEBUG("Key Slot MGMT: No PSA Key Slot available\n");
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
DEBUG("Key Slot MGMT: No PSA Key Slot available\n");
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
}
|
||||
|
||||
/* TODO: If no slots left: Look for slot in list with persistent key
|
||||
(key will be stored in persistent memory and slot can be reused) */
|
||||
|
||||
/* Remove key slote node from empty list and append to actual list */
|
||||
clist_node_t *new_slot = clist_rpop(empty_list);
|
||||
|
||||
@ -365,15 +436,15 @@ static psa_status_t psa_allocate_key_slot_in_list(psa_key_slot_t **p_slot,
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_allocate_empty_key_slot( psa_key_id_t *id,
|
||||
const psa_key_attributes_t *attr,
|
||||
psa_key_slot_t **p_slot)
|
||||
psa_status_t psa_allocate_empty_key_slot(psa_key_id_t *id,
|
||||
const psa_key_attributes_t *attr,
|
||||
psa_key_slot_t **p_slot)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *new_slot = NULL;
|
||||
|
||||
/* Change later, when we also have persistent keys */
|
||||
if (key_id_count == PSA_KEY_ID_VOLATILE_MAX) {
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(attr->lifetime) &&
|
||||
key_id_count == PSA_KEY_ID_VOLATILE_MAX) {
|
||||
DEBUG("Key Slot MGMT: Maximum key ID reached\n");
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
@ -392,7 +463,19 @@ psa_status_t psa_allocate_empty_key_slot( psa_key_id_t *id,
|
||||
*id = 0;
|
||||
return status;
|
||||
}
|
||||
*id = key_id_count++;
|
||||
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(attr->lifetime)) {
|
||||
*id = key_id_count++;
|
||||
}
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
else if (!psa_key_id_is_volatile(attr->id)) {
|
||||
*id = attr->id;
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
else {
|
||||
DEBUG("Key Slot MGMT: invalid lifetime or ID\n");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
*p_slot = new_slot;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
@ -456,7 +539,13 @@ psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime)
|
||||
if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
/* TODO: Implement persistent key storage */
|
||||
|
||||
#if IS_USED(MODULE_PSA_PERSISTENT_STORAGE)
|
||||
if (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == PSA_KEY_LIFETIME_PERSISTENT) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif /* MODULE_PSA_PERSISTENT_STORAGE */
|
||||
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -505,7 +594,7 @@ size_t psa_get_key_data_from_key_slot(const psa_key_slot_t *slot, uint8_t **key_
|
||||
return key_data_size;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_SECURE_ELEMENT) && PSA_PROTECTED_KEY_COUNT
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
psa_key_slot_number_t * psa_key_slot_get_slot_number(const psa_key_slot_t *slot)
|
||||
{
|
||||
return &(((psa_prot_key_slot_t *)slot)->key.slot_number);
|
||||
@ -540,7 +629,7 @@ void psa_get_public_key_data_from_key_slot(const psa_key_slot_t *slot, uint8_t *
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if PSA_PROTECTED_KEY_COUNT && IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
#if (PSA_PROTECTED_KEY_COUNT && PSA_ASYMMETRIC_KEYPAIR_COUNT)
|
||||
*pubkey_data = ((psa_prot_key_slot_t *)slot)->key.pubkey_data;
|
||||
*pubkey_data_len = &((psa_prot_key_slot_t *)slot)->key.pubkey_data_len;
|
||||
#endif
|
||||
|
3
sys/psa_crypto/psa_persistent_storage/Makefile
Normal file
3
sys/psa_crypto/psa_persistent_storage/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
INCLUDES += -I$(RIOTBASE)/sys/psa_crypto/include
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
546
sys/psa_crypto/psa_persistent_storage/psa_crypto_cbor_encoder.c
Normal file
546
sys/psa_crypto/psa_persistent_storage/psa_crypto_cbor_encoder.c
Normal file
@ -0,0 +1,546 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 sys_psa_crypto_slot_mgmt
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief API to encode PSA Crypto keys to CBOR for persistent storage
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "nanocbor/nanocbor.h"
|
||||
#include "psa_crypto_slot_management.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Convert a nanocbor error to a string for debugging
|
||||
*
|
||||
* @param res Nanocbor error value
|
||||
* @return const char*
|
||||
*/
|
||||
static const char *nanocbor_error_to_string(int res)
|
||||
{
|
||||
switch (res) {
|
||||
case NANOCBOR_ERR_OVERFLOW:
|
||||
return "NANOCBOR_ERR_OVERFLOW";
|
||||
case NANOCBOR_ERR_INVALID_TYPE:
|
||||
return "NANOCBOR_ERR_INVALID_TYPE";
|
||||
case NANOCBOR_ERR_END:
|
||||
return "NANOCBOR_ERR_END";
|
||||
case NANOCBOR_ERR_RECURSION:
|
||||
return "NANOCBOR_ERR_RECURSION";
|
||||
case NANOCBOR_NOT_FOUND:
|
||||
return "NANOCBOR_NOT_FOUND";
|
||||
default:
|
||||
return "Error value not recognized";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert nanocbor error to PSA Crypto status value
|
||||
*
|
||||
* @param res Nanocbor error value
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t nanocbor_error_to_psa_status(int res)
|
||||
{
|
||||
switch (res) {
|
||||
case NANOCBOR_ERR_END:
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
case NANOCBOR_NOT_FOUND:
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
default:
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a set of key attributes in CBOR
|
||||
*
|
||||
* @param enc Active nanocbor encoder
|
||||
* @param attr Pointer to key attributes to encode
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_encode_key_attributes(nanocbor_encoder_t *enc, psa_key_attributes_t *attr)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = nanocbor_fmt_array(enc, 5);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->id);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->type);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->bits);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->lifetime);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Policy */
|
||||
res = nanocbor_fmt_array(enc, 2);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->policy.usage);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_fmt_uint(enc, attr->policy.alg);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while encoding key attributes: %d = %s", res,
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Encode contents of a PSA key slot containing a protected key
|
||||
*
|
||||
* @param enc Active nanocbor encoder
|
||||
* @param slot Pointer to key slot to encode
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_encode_protected_key_slot(nanocbor_encoder_t *enc, psa_key_slot_t *slot)
|
||||
{
|
||||
int res;
|
||||
int key_array_size = 1;
|
||||
psa_key_slot_number_t *slot_no = psa_key_slot_get_slot_number(slot);
|
||||
|
||||
#if IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
|
||||
key_array_size = 2;
|
||||
}
|
||||
#endif /* MODULE_PSA_ASYMMETRIC */
|
||||
|
||||
res = nanocbor_fmt_array(enc, key_array_size);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = nanocbor_fmt_uint(enc, *slot_no);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
|
||||
uint8_t *pubkey_data;
|
||||
size_t *pubkey_data_len;
|
||||
psa_get_public_key_data_from_key_slot(slot, &pubkey_data, &pubkey_data_len);
|
||||
|
||||
res = nanocbor_put_bstr(enc, pubkey_data, *pubkey_data_len);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif /* MODULE_PSA_ASYMMETRIC */
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while encoding protected key: %d = %s", res,
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
/**
|
||||
* @brief Encode contents of a PSA key slot containing an asymmetric key pair
|
||||
*
|
||||
* @param enc Active nanocbor encoder
|
||||
* @param slot Pointer to key slot to encode
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_encode_asymmetric_key_pair(nanocbor_encoder_t *enc, psa_key_slot_t *slot)
|
||||
{
|
||||
int res;
|
||||
size_t *privkey_data_len;
|
||||
size_t *pubkey_data_len;
|
||||
uint8_t *privkey_data;
|
||||
uint8_t *pubkey_data;
|
||||
|
||||
psa_get_key_data_from_key_slot(slot, &privkey_data, &privkey_data_len);
|
||||
psa_get_public_key_data_from_key_slot(slot, &pubkey_data, &pubkey_data_len);
|
||||
|
||||
res = nanocbor_fmt_array(enc, 2); /* Contains private and public key*/
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = nanocbor_put_bstr(enc, privkey_data, *privkey_data_len);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = nanocbor_put_bstr(enc, pubkey_data, *pubkey_data_len);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while encoding asymmetric key: %d = %s", res,
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
#if PSA_SINGLE_KEY_COUNT
|
||||
/**
|
||||
* @brief Encode contents of a PSA key slot containing a single key
|
||||
*
|
||||
* @param enc Active nanocbor encoder
|
||||
* @param slot Pointer to key slot to encode
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_encode_single_key(nanocbor_encoder_t *enc, psa_key_slot_t *slot)
|
||||
{
|
||||
size_t *key_data_len;
|
||||
uint8_t *key_data;
|
||||
psa_get_key_data_from_key_slot(slot, &key_data, &key_data_len);
|
||||
|
||||
int res = nanocbor_put_bstr(enc, key_data, *key_data_len);
|
||||
if (res < 0) {
|
||||
DEBUG("[persistent storage] error while encoding single key: %d = %s", res,
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif /* PSA_SINGLE_KEY_COUNT */
|
||||
|
||||
psa_status_t psa_encode_key_slot(psa_key_slot_t *slot, uint8_t *output,
|
||||
size_t output_len, size_t *output_size)
|
||||
{
|
||||
int res;
|
||||
psa_status_t status;
|
||||
nanocbor_encoder_t enc;
|
||||
nanocbor_encoder_init(&enc, output, output_len);
|
||||
*output_size = 0;
|
||||
|
||||
/* Key Struct */
|
||||
res = nanocbor_fmt_array(&enc, 2);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = psa_encode_key_attributes(&enc, &slot->attr);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
if (psa_key_lifetime_is_external(slot->attr.lifetime)) {
|
||||
status = psa_encode_protected_key_slot(&enc, slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
|
||||
status = psa_encode_asymmetric_key_pair(&enc, slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
#if PSA_SINGLE_KEY_COUNT
|
||||
status = psa_encode_single_key(&enc, slot);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
goto done;
|
||||
#else
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
#endif /* PSA_SINGLE_KEY_COUNT */
|
||||
|
||||
done:
|
||||
*output_size = nanocbor_encoded_len(&enc);
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
printf("CBOR Encoded Length: %d\n", *output_size);
|
||||
puts("CBOR Encoded Key Slot:\n");
|
||||
for (size_t i = 0; i < output_len+1; i++){
|
||||
printf("%02x ", output[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while encoding key slot: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
|
||||
psa_status_t psa_decode_key_attributes(psa_key_attributes_t *attr,
|
||||
uint8_t *cbor_buf, size_t cbor_buf_size)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
nanocbor_value_t dec;
|
||||
nanocbor_decoder_init(&dec, cbor_buf, cbor_buf_size);
|
||||
|
||||
nanocbor_value_t key_slot;
|
||||
res = nanocbor_enter_array(&dec, &key_slot);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
nanocbor_value_t attr_dec;
|
||||
res = nanocbor_enter_array(&key_slot, &attr_dec);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint32(&attr_dec, &attr->id);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint16(&attr_dec, &attr->type);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint16(&attr_dec, &attr->bits);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint32(&attr_dec, &attr->lifetime);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
nanocbor_value_t policy;
|
||||
res = nanocbor_enter_array(&attr_dec, &policy);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint32(&policy, &attr->policy.usage);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
res = nanocbor_get_uint32(&policy, &attr->policy.alg);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
puts("Key Attributes:\n");
|
||||
printf("ID: %x\n", (int) attr->id);
|
||||
printf("Type: %x\n", (int) attr->type);
|
||||
printf("Bits: %d\n", (int) attr->bits);
|
||||
printf("Lifetime: %x\n", (int) attr->lifetime);
|
||||
printf("Usage: %x\n", (int) attr->policy.usage);
|
||||
printf("Algorithm: %x\n", (int) attr->policy.alg);
|
||||
#endif
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while decoding key attributes: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode CBOR encoded key data
|
||||
*
|
||||
* @param key Nanocbor value object containing CBOR encoding of the key data
|
||||
* @param key_data Output buffer to write key value
|
||||
* @param key_len Pointer to write actual key size
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_decode_key_data(nanocbor_value_t *key, uint8_t *key_data,
|
||||
size_t key_data_size, size_t *key_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
const uint8_t *buf;
|
||||
int res = nanocbor_get_bstr(key, &buf, &len);
|
||||
if (res < 0 || len <= 0) {
|
||||
key_len = NULL;
|
||||
key_data = NULL;
|
||||
DEBUG("[persistent storage] error while decoding key: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
|
||||
if (len > key_data_size) {
|
||||
key_len = NULL;
|
||||
key_data = NULL;
|
||||
DEBUG("[persistent storage] error while decoding key: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return PSA_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
|
||||
memcpy(key_data, buf, len);
|
||||
*key_len = len;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
/**
|
||||
* @brief Decode CBOR encoded protected key
|
||||
*
|
||||
* @param key Nanocbor value object containing CBOR encoded key data
|
||||
* @param slot Key slot to write decoded key to
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_decode_protected_key_slot(nanocbor_value_t *key, psa_key_slot_t *slot)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
nanocbor_value_t key_arr;
|
||||
res = nanocbor_enter_array(key, &key_arr);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
psa_key_slot_number_t *slot_no = psa_key_slot_get_slot_number(slot);
|
||||
res = nanocbor_get_uint64(&key_arr, slot_no);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_PSA_ASYMMETRIC)
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
|
||||
size_t *pubkey_data_len;
|
||||
uint8_t *pubkey_data;
|
||||
|
||||
psa_get_public_key_data_from_key_slot(slot, &pubkey_data, &pubkey_data_len);
|
||||
|
||||
return psa_decode_key_data(&key_arr, pubkey_data,
|
||||
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE, pubkey_data_len);
|
||||
}
|
||||
#endif /* MODULE_PSA_ASYMMETRIC */
|
||||
|
||||
return PSA_SUCCESS;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while decoding protected key slot: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
/**
|
||||
* @brief Decode CBOR encoded asymmetric key pair
|
||||
*
|
||||
* @param key Nanocbor value object containing CBOR encoded key data
|
||||
* @param slot Key slot to write decoded key to
|
||||
* @return psa_status_t
|
||||
*/
|
||||
static psa_status_t psa_decode_asymmetric_keypair_slot(nanocbor_value_t *key, psa_key_slot_t *slot)
|
||||
{
|
||||
int res = 0;
|
||||
psa_status_t status;
|
||||
size_t *privkey_data_len;
|
||||
size_t *pubkey_data_len;
|
||||
uint8_t *privkey_data;
|
||||
uint8_t *pubkey_data;
|
||||
|
||||
psa_get_key_data_from_key_slot(slot, &privkey_data, &privkey_data_len);
|
||||
psa_get_public_key_data_from_key_slot(slot, &pubkey_data, &pubkey_data_len);
|
||||
|
||||
nanocbor_value_t key_arr;
|
||||
res = nanocbor_enter_array(key, &key_arr);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = psa_decode_key_data(&key_arr, privkey_data,
|
||||
PSA_BITS_TO_BYTES(PSA_MAX_PRIV_KEY_SIZE), privkey_data_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return psa_decode_key_data(&key_arr, pubkey_data,
|
||||
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE, pubkey_data_len);
|
||||
error:
|
||||
DEBUG("[persistent storage] error while decoding asymmetric key pair: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
psa_status_t psa_decode_key_slot_data(psa_key_slot_t *slot, uint8_t *cbor_buf, size_t cbor_buf_size)
|
||||
{
|
||||
int res = 0;
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
|
||||
nanocbor_value_t dec;
|
||||
nanocbor_decoder_init(&dec, cbor_buf, cbor_buf_size);
|
||||
|
||||
nanocbor_value_t key_slot;
|
||||
res = nanocbor_enter_array(&dec, &key_slot);
|
||||
if (res < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* We should have decoded the attributes before, so we can skip them here */
|
||||
nanocbor_skip(&key_slot);
|
||||
|
||||
#if PSA_PROTECTED_KEY_COUNT
|
||||
if (psa_key_lifetime_is_external(slot->attr.lifetime)) {
|
||||
return psa_decode_protected_key_slot(&key_slot, slot);
|
||||
}
|
||||
#endif /* PSA_PROTECTED_KEY_COUNT */
|
||||
|
||||
#if PSA_ASYMMETRIC_KEYPAIR_COUNT
|
||||
if (PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
|
||||
return psa_decode_asymmetric_keypair_slot(&key_slot, slot);
|
||||
}
|
||||
#endif /* PSA_ASYMMETRIC_KEYPAIR_COUNT */
|
||||
|
||||
#if PSA_SINGLE_KEY_COUNT
|
||||
size_t *key_data_len;
|
||||
uint8_t *key_data;
|
||||
|
||||
psa_get_key_data_from_key_slot(slot, &key_data, &key_data_len);
|
||||
|
||||
return psa_decode_key_data(&key_slot, key_data, PSA_MAX_KEY_DATA_SIZE, key_data_len);
|
||||
#endif /* PSA_SINGLE_KEY_COUNT */
|
||||
|
||||
return status;
|
||||
|
||||
error:
|
||||
DEBUG("[persistent storage] error while decoding key slot: %s",
|
||||
nanocbor_error_to_string(res));
|
||||
return nanocbor_error_to_psa_status(res);
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 Implementation of persistent storage for PSA Crypto keys
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_slot_management.h"
|
||||
#include "board.h"
|
||||
#include "vfs.h"
|
||||
#include "fs/littlefs2_fs.h"
|
||||
#include "mtd.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
XFA_USE(vfs_mount_t, vfs_mountpoints_xfa);
|
||||
|
||||
#define UINT32_T_MAX_STRING_LEN (10)
|
||||
|
||||
/* dir path needs to be as long as mount point + psa_key_id_t as string */
|
||||
#define STRING_PATH_LEN (strlen(vfs_mountpoints_xfa[0].mount_point) + \
|
||||
UINT32_T_MAX_STRING_LEN)
|
||||
|
||||
psa_status_t psa_write_encoded_key_slot_to_file(psa_key_id_t id,
|
||||
uint8_t* input,
|
||||
size_t input_len)
|
||||
{
|
||||
/* dir path needs to be as long as mount point + psa_key_id_t as string */
|
||||
char string_path[STRING_PATH_LEN];
|
||||
|
||||
sprintf(string_path, "%s/%d", vfs_mountpoints_xfa[0].mount_point, (int) id);
|
||||
|
||||
/* Check whether file already exists */
|
||||
int fd = vfs_open(string_path, O_RDWR, 0);
|
||||
if (fd >= 0) {
|
||||
DEBUG("[psa_crypto] persist key: key with this ID already exists in storage: %d\n", fd);
|
||||
vfs_close(fd);
|
||||
return PSA_ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
/* If file does not exist, create one */
|
||||
fd = vfs_open(string_path, O_CREAT | O_RDWR, 0);
|
||||
|
||||
if (fd <= 0) {
|
||||
DEBUG("[psa_crypto] persist key: Can not open file: %d\n", fd);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
if (vfs_write(fd, input, input_len) < 0) {
|
||||
DEBUG("[psa_crypto] persist key: Can not write to file: %d\n", fd);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
if (vfs_close(fd) != 0) {
|
||||
DEBUG("[psa_crypto] persist key: Can not close file: %d\n", fd);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_read_encoded_key_slot_from_file(psa_key_id_t id,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_data_len)
|
||||
{
|
||||
char string_path[STRING_PATH_LEN];
|
||||
|
||||
sprintf(string_path, "%s/%d", vfs_mountpoints_xfa[0].mount_point, (int) id);
|
||||
|
||||
int fd = vfs_open(string_path, O_RDONLY, 0);
|
||||
|
||||
if (fd <= 0) {
|
||||
DEBUG("[psa_crypto] read persisted key: Can not open file: %d\n", fd);
|
||||
return (fd == -2 ? PSA_ERROR_DOES_NOT_EXIST : PSA_ERROR_STORAGE_FAILURE);
|
||||
}
|
||||
|
||||
ssize_t data_bytes = vfs_read(fd, output, output_size);
|
||||
if (data_bytes < 0) {
|
||||
DEBUG("[psa_crypto] read persisted key: Can not read from file\n");
|
||||
return (fd == -2 ? PSA_ERROR_DOES_NOT_EXIST : PSA_ERROR_STORAGE_FAILURE);
|
||||
}
|
||||
|
||||
if (vfs_close(fd) != 0) {
|
||||
|
||||
DEBUG("[psa_crypto] read persisted key: Can not close file: %d\n", fd);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
*output_data_len = data_bytes;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t psa_destroy_persistent_key(psa_key_id_t key_id)
|
||||
{
|
||||
if (psa_key_id_is_volatile(key_id)) {
|
||||
DEBUG("[psa_crypto] persist key: ID is volatile\n");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
char string_path[STRING_PATH_LEN];
|
||||
|
||||
sprintf(string_path, "%s/%d", vfs_mountpoints_xfa[0].mount_point, (int) key_id);
|
||||
|
||||
int fd = vfs_unlink(string_path);
|
||||
if (fd < 0) {
|
||||
DEBUG("[psa_crypto] destroy persisted key: Can not unlink file: %d\n", fd);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
24
tests/sys/psa_crypto_cbor_encoder/Makefile
Normal file
24
tests/sys/psa_crypto_cbor_encoder/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
include ../Makefile.sys_common
|
||||
|
||||
USEMODULE += embunit
|
||||
|
||||
# This configuration also builds the backend implementations for all those selected
|
||||
# modules, some of which depend on the PSA hash functions. So to make this test
|
||||
# compile, we add the psa_hash module.
|
||||
USEMODULE += psa_hash
|
||||
USEMODULE += psa_hash_sha_256
|
||||
|
||||
USEMODULE += psa_crypto
|
||||
USEMODULE += psa_persistent_storage
|
||||
|
||||
USEMODULE += psa_cipher
|
||||
USEMODULE += psa_cipher_aes_128_cbc
|
||||
|
||||
USEMODULE += psa_asymmetric
|
||||
USEMODULE += psa_asymmetric_ecc_p256r1
|
||||
|
||||
CFLAGS += -DCONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT=1
|
||||
CFLAGS += -DCONFIG_PSA_SINGLE_KEY_COUNT=1
|
||||
CFLAGS += -DCONFIG_PSA_PROTECTED_KEY_COUNT=1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
14
tests/sys/psa_crypto_cbor_encoder/Makefile.ci
Normal file
14
tests/sys/psa_crypto_cbor_encoder/Makefile.ci
Normal file
@ -0,0 +1,14 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
atmega8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-l011k4 \
|
||||
samd10-xmini \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
#
|
31
tests/sys/psa_crypto_cbor_encoder/main.c
Normal file
31
tests/sys/psa_crypto_cbor_encoder/main.c
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for the PSA Crypto key encoding module
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "tests_psa_cbor_enc_dec.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
TESTS_RUN(tests_psa_crypto_enc_dec_single_key());
|
||||
TESTS_RUN(tests_psa_crypto_enc_dec_keypair());
|
||||
TESTS_RUN(tests_psa_crypto_enc_dec_protected_key());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Tests CBOR encoding of a PSA Crypto asymmetric key pair slot.
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_cbor_encoder.h"
|
||||
#include "tests_psa_cbor_enc_dec.h"
|
||||
|
||||
/**
|
||||
* @brief Data has been obtained by manually encoding and decoding keys,
|
||||
* until they fit the desired format and checking the output with
|
||||
* https://cbor.me.
|
||||
*
|
||||
* Diagnostic notation:
|
||||
* [
|
||||
* [268435459, 28946, 256, 1, [12288, 100664841]],
|
||||
* [h'27FC4D41F3DE49F786314B74AA67DE4BA961C38F4F896F045A537102B43D2039',
|
||||
* h'0456CB81D1CBDE44F51DCCB12602670D76DDE784ED8D30721CCA5059F920AD62
|
||||
* 87749EC9CB2675C51B69A68956102E8F6F7257B9B993ED8899EAFD53823DCAB641']
|
||||
* ]
|
||||
*/
|
||||
static uint8_t cbor_encoded_data[] = {
|
||||
0x82, 0x85, 0x1a, 0x10, 0x00, 0x00, 0x03, 0x19,
|
||||
0x71, 0x12, 0x19, 0x01, 0x00, 0x01, 0x82, 0x19,
|
||||
0x30, 0x00, 0x1a, 0x06, 0x00, 0x06, 0x09, 0x82,
|
||||
0x58, 0x20, 0x27, 0xfc, 0x4d, 0x41, 0xf3, 0xde,
|
||||
0x49, 0xf7, 0x86, 0x31, 0x4b, 0x74, 0xaa, 0x67,
|
||||
0xde, 0x4b, 0xa9, 0x61, 0xc3, 0x8f, 0x4f, 0x89,
|
||||
0x6f, 0x04, 0x5a, 0x53, 0x71, 0x02, 0xb4, 0x3d,
|
||||
0x20, 0x39, 0x58, 0x41, 0x04, 0x56, 0xcb, 0x81,
|
||||
0xd1, 0xcb, 0xde, 0x44, 0xf5, 0x1d, 0xcc, 0xb1,
|
||||
0x26, 0x02, 0x67, 0x0d, 0x76, 0xdd, 0xe7, 0x84,
|
||||
0xed, 0x8d, 0x30, 0x72, 0x1c, 0xca, 0x50, 0x59,
|
||||
0xf9, 0x20, 0xad, 0x62, 0x87, 0x74, 0x9e, 0xc9,
|
||||
0xcb, 0x26, 0x75, 0xc5, 0x1b, 0x69, 0xa6, 0x89,
|
||||
0x56, 0x10, 0x2e, 0x8f, 0x6f, 0x72, 0x57, 0xb9,
|
||||
0xb9, 0x93, 0xed, 0x88, 0x99, 0xea, 0xfd, 0x53,
|
||||
0x82, 0x3d, 0xca, 0xb6, 0x41
|
||||
};
|
||||
|
||||
static void _init_key_slot(psa_key_pair_slot_t *slot)
|
||||
{
|
||||
psa_key_lifetime_t lifetime = 1;
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
|
||||
|
||||
psa_set_key_lifetime(&slot->attr, lifetime);
|
||||
psa_set_key_algorithm(&slot->attr, ECC_ALG);
|
||||
psa_set_key_usage_flags(&slot->attr, usage);
|
||||
psa_set_key_type(&slot->attr, ECC_KEY_TYPE);
|
||||
psa_set_key_bits(&slot->attr, ECC_KEY_SIZE);
|
||||
psa_set_key_id(&slot->attr, 0x10000003);
|
||||
|
||||
memcpy(slot->key.privkey_data, privkey, sizeof(privkey));
|
||||
slot->key.privkey_data_len = sizeof(privkey);
|
||||
|
||||
memcpy(slot->key.pubkey_data, pubkey, sizeof(pubkey));
|
||||
slot->key.pubkey_data_len = sizeof(pubkey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CBOR encoding of key pair slot should equal @c cbor_encoded_data
|
||||
*/
|
||||
static void test_encode_asymmetric_keypair_slot(void)
|
||||
{
|
||||
size_t encoded_size;
|
||||
uint8_t cbor_enc[sizeof(cbor_encoded_data)];
|
||||
psa_key_pair_slot_t slot;
|
||||
_init_key_slot(&slot);
|
||||
|
||||
TEST_ASSERT_PSA(psa_encode_key_slot((psa_key_slot_t *)&slot, cbor_enc, sizeof(cbor_enc), &encoded_size));
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(cbor_encoded_data), encoded_size);
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(cbor_enc, cbor_encoded_data,
|
||||
encoded_size), "wrong cbor encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decoded key slot should equal key slot structure initialized
|
||||
* in @c test_encode_asymmetric_keypair_slot.
|
||||
*/
|
||||
static void test_decode_asymmetric_keypair_slot(void)
|
||||
{
|
||||
psa_key_pair_slot_t slot;
|
||||
|
||||
TEST_ASSERT_PSA(psa_decode_key_attributes(&slot.attr, cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_PSA(psa_decode_key_slot_data((psa_key_slot_t *)&slot, cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp((uint8_t *)&slot, (uint8_t *)&slot,
|
||||
sizeof(psa_key_pair_slot_t)), "wrong cbor decoding");
|
||||
}
|
||||
|
||||
Test* tests_psa_crypto_enc_dec_keypair(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_encode_asymmetric_keypair_slot),
|
||||
new_TestFixture(test_decode_asymmetric_keypair_slot),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(psa_crypto_enc_dec_keypair_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&psa_crypto_enc_dec_keypair_tests;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Tests CBOR encoding of PSA Crypto protected key slots
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_cbor_encoder.h"
|
||||
#include "tests_psa_cbor_enc_dec.h"
|
||||
|
||||
/**
|
||||
* @brief Testdata has been obtained by manually encoding and decoding keys,
|
||||
* until they fit the desired format and checking the output with
|
||||
* https://cbor.me.
|
||||
*
|
||||
* Diagnostic notation:
|
||||
* [
|
||||
* [8, 9216, 128, 2147483648, [768, 71319552]],
|
||||
* [4]
|
||||
* ]
|
||||
*/
|
||||
static uint8_t cbor_encoded_data[] = {
|
||||
0x82, 0x85, 0x08, 0x19, 0x24, 0x00, 0x18, 0x80,
|
||||
0x1a, 0x80, 0x00, 0x00, 0x00, 0x82, 0x19, 0x03,
|
||||
0x00, 0x1a, 0x04, 0x40, 0x40, 0x00, 0x81, 0x04
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Testdata has been obtained by manually encoding and decoding keys,
|
||||
* until they fit the desired format and checking the output with
|
||||
* https://cbor.me.
|
||||
*
|
||||
* Diagnostic notation:
|
||||
* [
|
||||
* [8, 28946, 256, 2147483648, [12288, 100664841]],
|
||||
* [4, h'0456CB81D1CBDE44F51DCCB12602670D76DDE784ED8D30721CCA5059F920AD62877
|
||||
* 49EC9CB2675C51B69A68956102E8F6F7257B9B993ED8899EAFD53823DCAB641']
|
||||
* ]
|
||||
*/
|
||||
static uint8_t cbor_encoded_data_with_pubkey[] = {
|
||||
0x82, 0x85, 0x08, 0x19, 0x71, 0x12, 0x19, 0x01,
|
||||
0x00, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x82, 0x19,
|
||||
0x30, 0x00, 0x1a, 0x06, 0x00, 0x06, 0x09, 0x82,
|
||||
0x04, 0x58, 0x41, 0x04, 0x56, 0xcb, 0x81, 0xd1,
|
||||
0xcb, 0xde, 0x44, 0xf5, 0x1d, 0xcc, 0xb1, 0x26,
|
||||
0x02, 0x67, 0x0d, 0x76, 0xdd, 0xe7, 0x84, 0xed,
|
||||
0x8d, 0x30, 0x72, 0x1c, 0xca, 0x50, 0x59, 0xf9,
|
||||
0x20, 0xad, 0x62, 0x87, 0x74, 0x9e, 0xc9, 0xcb,
|
||||
0x26, 0x75, 0xc5, 0x1b, 0x69, 0xa6, 0x89, 0x56,
|
||||
0x10, 0x2e, 0x8f, 0x6f, 0x72, 0x57, 0xb9, 0xb9,
|
||||
0x93, 0xed, 0x88, 0x99, 0xea, 0xfd, 0x53, 0x82,
|
||||
0x3d, 0xca, 0xb6, 0x41
|
||||
};
|
||||
|
||||
static void _init_key_slot(psa_prot_key_slot_t *slot, int is_pubkey)
|
||||
{
|
||||
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION
|
||||
(PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_LOCATION_SE_MIN);
|
||||
psa_set_key_lifetime(&slot->attr, lifetime);
|
||||
psa_set_key_id(&slot->attr, 8);
|
||||
slot->key.slot_number = 4;
|
||||
|
||||
if (!is_pubkey) {
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
|
||||
psa_set_key_algorithm(&slot->attr, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_usage_flags(&slot->attr, usage);
|
||||
psa_set_key_type(&slot->attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&slot->attr, PSA_BYTES_TO_BITS(sizeof(AES_KEY)));
|
||||
}
|
||||
else {
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
|
||||
psa_set_key_algorithm(&slot->attr, ECC_ALG);
|
||||
psa_set_key_usage_flags(&slot->attr, usage);
|
||||
psa_set_key_type(&slot->attr, ECC_KEY_TYPE);
|
||||
psa_set_key_bits(&slot->attr, ECC_KEY_SIZE);
|
||||
psa_set_key_id(&slot->attr, 8);
|
||||
|
||||
memcpy(slot->key.pubkey_data, pubkey, sizeof(pubkey));
|
||||
slot->key.pubkey_data_len = sizeof(pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CBOR encoding of key pair slot should equal @c cbor_encoded_data
|
||||
*/
|
||||
static void test_encode_protected_key_slot(void)
|
||||
{
|
||||
size_t encoded_size;
|
||||
uint8_t cbor_enc[sizeof(cbor_encoded_data)];
|
||||
psa_prot_key_slot_t slot;
|
||||
_init_key_slot(&slot, 0);
|
||||
|
||||
TEST_ASSERT_PSA(psa_encode_key_slot((psa_key_slot_t *)&slot, cbor_enc, sizeof(cbor_enc), &encoded_size));
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(cbor_encoded_data), encoded_size);
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(cbor_enc, cbor_encoded_data, encoded_size),
|
||||
"wrong cbor encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CBOR encoding of key pair slot should equal @c cbor_encoded_data_with_pubkey
|
||||
*/
|
||||
static void test_encode_protected_key_slot_with_pubkey(void)
|
||||
{
|
||||
size_t encoded_size;
|
||||
uint8_t cbor_enc_with_pubkey[sizeof(cbor_encoded_data_with_pubkey)];
|
||||
psa_prot_key_slot_t slot;
|
||||
_init_key_slot(&slot, 1);
|
||||
|
||||
TEST_ASSERT_PSA(psa_encode_key_slot((psa_key_slot_t *)&slot, cbor_enc_with_pubkey, sizeof(cbor_enc_with_pubkey), &encoded_size));
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(cbor_encoded_data_with_pubkey), encoded_size);
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(cbor_enc_with_pubkey, cbor_encoded_data_with_pubkey,
|
||||
encoded_size), "wrong cbor encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decoded key slot should equal key slot structure initialized
|
||||
* in @c test_encode_protected_key_slot.
|
||||
*/
|
||||
static void test_decode_protected_key_slot(void)
|
||||
{
|
||||
psa_prot_key_slot_t slot;
|
||||
|
||||
TEST_ASSERT_PSA(psa_decode_key_attributes(&slot.attr, cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_PSA(psa_decode_key_slot_data((psa_key_slot_t *)&slot, cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp((uint8_t *)&slot, (uint8_t *)&slot,
|
||||
sizeof(psa_prot_key_slot_t)), "wrong cbor decoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decoded key slot should equal key slot structure initialized
|
||||
* in @c test_encode_protected_key_slot_with_pubkey.
|
||||
*/
|
||||
static void test_decode_protected_key_slot_with_pubkey(void)
|
||||
{
|
||||
psa_prot_key_slot_t slot;
|
||||
|
||||
TEST_ASSERT_PSA(psa_decode_key_attributes(&slot.attr, cbor_encoded_data_with_pubkey, sizeof(cbor_encoded_data_with_pubkey)));
|
||||
TEST_ASSERT_PSA(psa_decode_key_slot_data((psa_key_slot_t *)&slot, cbor_encoded_data_with_pubkey, sizeof(cbor_encoded_data_with_pubkey)));
|
||||
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp((uint8_t *)&slot, (uint8_t *)&slot,
|
||||
sizeof(psa_prot_key_slot_t)), "wrong cbor decoding");
|
||||
}
|
||||
|
||||
Test* tests_psa_crypto_enc_dec_protected_key(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_encode_protected_key_slot),
|
||||
new_TestFixture(test_decode_protected_key_slot),
|
||||
new_TestFixture(test_encode_protected_key_slot_with_pubkey),
|
||||
new_TestFixture(test_decode_protected_key_slot_with_pubkey)
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(psa_crypto_enc_dec_protected_key_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&psa_crypto_enc_dec_protected_key_tests;
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Tests CBOR encoding of a PSA Crypto key slot containing one single key
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_cbor_encoder.h"
|
||||
#include "tests_psa_cbor_enc_dec.h"
|
||||
|
||||
/**
|
||||
* @brief Data has been obtained by manually encoding and decoding keys,
|
||||
* until they fit the desired format and checking the output with
|
||||
* https://cbor.me.
|
||||
*
|
||||
* Diagnostic notation:
|
||||
* [
|
||||
* [268435459, 9216, 128, 1, [256, 71319552]],
|
||||
* h'2B7E151628AED218ABF7158809CF4F3C'
|
||||
* ]
|
||||
*/
|
||||
static uint8_t cbor_encoded_data[] = {
|
||||
0x82, 0x85, 0x1a, 0x10, 0x00, 0x00, 0x03, 0x19,
|
||||
0x24, 0x00, 0x18, 0x80, 0x01, 0x82, 0x19, 0x01,
|
||||
0x00, 0x1a, 0x04, 0x40, 0x40, 0x00, 0x50, 0x2b,
|
||||
0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0x18, 0xab,
|
||||
0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
|
||||
static void _init_key_slot(psa_key_slot_t *slot)
|
||||
{
|
||||
psa_set_key_type(&slot->attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_algorithm(&slot->attr, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_bits(&slot->attr, PSA_BYTES_TO_BITS(sizeof(AES_KEY)));
|
||||
psa_set_key_lifetime(&slot->attr, 0x00000001);
|
||||
psa_set_key_usage_flags(&slot->attr, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_id(&slot->attr, 0x10000003);
|
||||
|
||||
memcpy(slot->key.data, AES_KEY, sizeof(AES_KEY));
|
||||
slot->key.data_len = sizeof(AES_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CBOR encoding of key pair slot should equal @c cbor_encoded_data
|
||||
*/
|
||||
static void test_encode_single_key_slot(void)
|
||||
{
|
||||
size_t encoded_size;
|
||||
uint8_t cbor_enc[sizeof(cbor_encoded_data)];
|
||||
psa_key_slot_t slot;
|
||||
_init_key_slot(&slot);
|
||||
|
||||
TEST_ASSERT_PSA(psa_encode_key_slot(&slot, cbor_enc, sizeof(cbor_enc), &encoded_size));
|
||||
TEST_ASSERT_EQUAL_INT(sizeof(cbor_encoded_data), encoded_size);
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(cbor_enc, cbor_encoded_data,
|
||||
encoded_size), "wrong cbor encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decoded key slot should equal key slot structure initialized
|
||||
* in @c test_encode_single_key_slot.
|
||||
*/
|
||||
static void test_decode_single_key_slot(void)
|
||||
{
|
||||
psa_key_slot_t slot;
|
||||
|
||||
TEST_ASSERT_PSA(psa_decode_key_attributes(&(slot.attr), cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_PSA(psa_decode_key_slot_data(&slot, cbor_encoded_data, sizeof(cbor_encoded_data)));
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp((uint8_t *)&slot, (uint8_t *)&slot,
|
||||
sizeof(psa_key_slot_t)), "wrong cbor decoding");
|
||||
}
|
||||
|
||||
Test* tests_psa_crypto_enc_dec_single_key(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_encode_single_key_slot),
|
||||
new_TestFixture(test_decode_single_key_slot),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(psa_crypto_enc_dec_single_key_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&psa_crypto_enc_dec_single_key_tests;
|
||||
}
|
14
tests/sys/psa_crypto_cbor_encoder/tests/01-run.py
Executable file
14
tests/sys/psa_crypto_cbor_encoder/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2023 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
71
tests/sys/psa_crypto_cbor_encoder/tests_psa_cbor_enc_dec.h
Normal file
71
tests/sys/psa_crypto_cbor_encoder/tests_psa_cbor_enc_dec.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
* @defgroup <name> <description>
|
||||
* @{
|
||||
*
|
||||
* @file tests_psa_cbor_enc_dec.h
|
||||
* @brief
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TESTS_PSA_CBOR_ENC_DEC_H
|
||||
#define TESTS_PSA_CBOR_ENC_DEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "embUnit.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TEST_ASSERT_PSA(func_) TEST_ASSERT_MESSAGE((func_) == PSA_SUCCESS, #func_ " failed");
|
||||
|
||||
#define ECC_KEY_SIZE (256)
|
||||
#define ECC_KEY_TYPE (PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1))
|
||||
#define ECC_ALG_HASH (PSA_ALG_SHA_256)
|
||||
#define ECC_ALG (PSA_ALG_ECDSA(ECC_ALG_HASH))
|
||||
|
||||
static const uint8_t privkey[] = {
|
||||
0x27, 0xfc, 0x4d, 0x41, 0xf3, 0xde, 0x49, 0xf7,
|
||||
0x86, 0x31, 0x4b, 0x74, 0xaa, 0x67, 0xde, 0x4b,
|
||||
0xa9, 0x61, 0xc3, 0x8f, 0x4f, 0x89, 0x6f, 0x04,
|
||||
0x5a, 0x53, 0x71, 0x02, 0xb4, 0x3d, 0x20, 0x39
|
||||
};
|
||||
|
||||
static const uint8_t pubkey[] = {
|
||||
0x04,
|
||||
0x56, 0xcb, 0x81, 0xd1, 0xcb, 0xde, 0x44, 0xf5,
|
||||
0x1d, 0xcc, 0xb1, 0x26, 0x02, 0x67, 0x0d, 0x76,
|
||||
0xdd, 0xe7, 0x84, 0xed, 0x8d, 0x30, 0x72, 0x1c,
|
||||
0xca, 0x50, 0x59, 0xf9, 0x20, 0xad, 0x62, 0x87,
|
||||
0x74, 0x9e, 0xc9, 0xcb, 0x26, 0x75, 0xc5, 0x1b,
|
||||
0x69, 0xa6, 0x89, 0x56, 0x10, 0x2e, 0x8f, 0x6f,
|
||||
0x72, 0x57, 0xb9, 0xb9, 0x93, 0xed, 0x88, 0x99,
|
||||
0xea, 0xfd, 0x53, 0x82, 0x3d, 0xca, 0xb6, 0x41
|
||||
};
|
||||
|
||||
static const uint8_t AES_KEY[] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0x18,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
|
||||
Test* tests_psa_crypto_enc_dec_single_key(void);
|
||||
Test* tests_psa_crypto_enc_dec_keypair(void);
|
||||
Test* tests_psa_crypto_enc_dec_protected_key(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TESTS_PSA_CBOR_ENC_DEC_H */
|
||||
/** @} */
|
23
tests/sys/psa_crypto_persistent_storage/Makefile
Normal file
23
tests/sys/psa_crypto_persistent_storage/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
include ../Makefile.sys_common
|
||||
|
||||
BOARD_WHITELIST = \
|
||||
native \
|
||||
nrf52840dk \
|
||||
#
|
||||
|
||||
USEMODULE += embunit
|
||||
|
||||
USEMODULE += psa_crypto
|
||||
USEMODULE += psa_persistent_storage
|
||||
|
||||
USEMODULE += psa_cipher
|
||||
USEMODULE += psa_cipher_aes_128_cbc
|
||||
|
||||
USEMODULE += psa_asymmetric
|
||||
USEMODULE += psa_asymmetric_ecc_ed25519
|
||||
|
||||
CFLAGS += -DCONFIG_PSA_SINGLE_KEY_COUNT=1
|
||||
CFLAGS += -DCONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT=1
|
||||
CFLAGS += -DTHREAD_STACKSIZE_MAIN=\(4*THREAD_STACKSIZE_DEFAULT\)
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
33
tests/sys/psa_crypto_persistent_storage/main.c
Normal file
33
tests/sys/psa_crypto_persistent_storage/main.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Test application for the PSA Crypto key encoding module
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "tests_psa_persistent_storage.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TESTS_START();
|
||||
psa_crypto_init();
|
||||
TESTS_RUN(tests_psa_persistent_single_key_storage());
|
||||
TESTS_RUN(tests_psa_persistent_asym_keypair_storage());
|
||||
TESTS_RUN(tests_psa_fail_overwrite_existing_key());
|
||||
TESTS_END();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Verify that PSA Crypto keys cannot be overwritten in storage
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "tests_psa_persistent_storage.h"
|
||||
|
||||
static psa_key_id_t key_id = 1;
|
||||
|
||||
/**
|
||||
* @brief A persistently stored key must not be overwritten by new key with same ID
|
||||
*/
|
||||
static void test_psa_fail_overwrite_existing_key(void)
|
||||
{
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT;
|
||||
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_usage_flags(&attr, usage);
|
||||
psa_set_key_bits(&attr, 128);
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_id(&attr, key_id);
|
||||
|
||||
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION
|
||||
(PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LOCATION_LOCAL_STORAGE);
|
||||
psa_set_key_lifetime(&attr, lifetime);
|
||||
|
||||
/* Import persistent key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_import_key(&attr, KEY_128, AES_128_KEY_SIZE, &key_id));
|
||||
|
||||
/* Import different key with same ID, should fail */
|
||||
TEST_ASSERT_PSA_ALREADY_EXISTS(psa_import_key(&attr, OVERWRITE_KEY_128, AES_128_KEY_SIZE, &key_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief After deleting a persistent key, a new key with same ID can be imported
|
||||
*/
|
||||
static void test_psa_delete_key_and_import_key_with_same_id(void)
|
||||
{
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT;
|
||||
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_usage_flags(&attr, usage);
|
||||
psa_set_key_bits(&attr, 128);
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_id(&attr, key_id);
|
||||
|
||||
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION
|
||||
(PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LOCATION_LOCAL_STORAGE);
|
||||
psa_set_key_lifetime(&attr, lifetime);
|
||||
|
||||
/* Destroy persistent key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(key_id));
|
||||
|
||||
/* Import different key with same ID, should succeed */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_import_key(&attr, OVERWRITE_KEY_128, AES_128_KEY_SIZE, &key_id));
|
||||
|
||||
/* Destroy persistent key again, to clean up */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(key_id));
|
||||
}
|
||||
|
||||
Test* tests_psa_fail_overwrite_existing_key(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_psa_fail_overwrite_existing_key),
|
||||
new_TestFixture(test_psa_delete_key_and_import_key_with_same_id),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(tests_psa_fail_overwrite_existing_key_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&tests_psa_fail_overwrite_existing_key_tests;
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Tests CBOR encoding of a PSA Crypto asymmetric key pair slot.
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "tests_psa_persistent_storage.h"
|
||||
|
||||
#define EDDSA_MESSAGE_SIZE (127)
|
||||
|
||||
#define ECC_KEY_SIZE (255)
|
||||
#define ECC_KEY_TYPE (PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS))
|
||||
#define ECC_ALG (PSA_ALG_PURE_EDDSA)
|
||||
|
||||
#define ECC_PUBLIC_KEY_SIZE (PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(ECC_KEY_TYPE, ECC_KEY_SIZE))
|
||||
#define SIGNATURE_SIZE (PSA_SIGN_OUTPUT_SIZE(ECC_KEY_TYPE, ECC_KEY_SIZE, ECC_ALG))
|
||||
|
||||
static psa_key_attributes_t privkey_attr;
|
||||
static psa_key_attributes_t pubkey_attr;
|
||||
|
||||
static psa_key_id_t privkey_id = 1;
|
||||
static psa_key_id_t pubkey_id = 2;
|
||||
static psa_key_id_t overwrite_privkey_id = 3;
|
||||
|
||||
static const uint8_t msg[EDDSA_MESSAGE_SIZE] = { 0x0b };
|
||||
|
||||
static void _test_setup(void)
|
||||
{
|
||||
uint8_t public_key[ECC_PUBLIC_KEY_SIZE];
|
||||
size_t pubkey_length;
|
||||
|
||||
privkey_attr = psa_key_attributes_init();
|
||||
pubkey_attr = psa_key_attributes_init();
|
||||
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE;
|
||||
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION
|
||||
(PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LOCATION_LOCAL_STORAGE);
|
||||
|
||||
psa_set_key_algorithm(&privkey_attr, ECC_ALG);
|
||||
psa_set_key_usage_flags(&privkey_attr, usage);
|
||||
psa_set_key_type(&privkey_attr, ECC_KEY_TYPE);
|
||||
psa_set_key_bits(&privkey_attr, ECC_KEY_SIZE);
|
||||
psa_set_key_id(&privkey_attr, privkey_id);
|
||||
psa_set_key_lifetime(&privkey_attr, lifetime);
|
||||
|
||||
/* Generate persistent key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_generate_key(&privkey_attr, &privkey_id));
|
||||
|
||||
/* Export and import public key for verification */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_export_public_key(privkey_id, public_key,
|
||||
sizeof(public_key), &pubkey_length));
|
||||
|
||||
psa_set_key_usage_flags(&pubkey_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
|
||||
psa_set_key_algorithm(&pubkey_attr, ECC_ALG);
|
||||
psa_set_key_bits(&pubkey_attr, PSA_BYTES_TO_BITS(pubkey_length));
|
||||
psa_set_key_type(&pubkey_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
|
||||
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_import_key(&pubkey_attr, public_key, pubkey_length, &pubkey_id));
|
||||
}
|
||||
|
||||
static void _test_destroy_keys(int cleanup)
|
||||
{
|
||||
/* Destroy first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(privkey_id));
|
||||
|
||||
/* Destroy second key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(pubkey_id));
|
||||
|
||||
if (cleanup) {
|
||||
/* Destroy last key, just to clean up */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(overwrite_privkey_id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A persistently stored key should still be accessible after
|
||||
* overwriting it in local memory
|
||||
*/
|
||||
static void test_psa_store_persistent_asym_keypair(void)
|
||||
{
|
||||
uint8_t signature[SIGNATURE_SIZE];
|
||||
size_t sig_length;
|
||||
|
||||
_test_setup();
|
||||
|
||||
/* Generate second keypair to overwrite the first one in volatile memory */
|
||||
psa_set_key_id(&privkey_attr, overwrite_privkey_id);
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_generate_key(&privkey_attr, &overwrite_privkey_id));
|
||||
|
||||
/* Generate message signature with first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_sign_message(privkey_id, ECC_ALG, msg, sizeof(msg), signature, sizeof(signature), &sig_length));
|
||||
|
||||
/* Verify signature with public key of first keypair */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_verify_message(pubkey_id, ECC_ALG, msg,
|
||||
sizeof(msg), signature, sig_length));
|
||||
|
||||
_test_destroy_keys(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief After destroying a persistent key, it should not be available anymore
|
||||
*/
|
||||
static void test_psa_delete_persistent_asym_keypair(void)
|
||||
{
|
||||
uint8_t signature[SIGNATURE_SIZE];
|
||||
size_t sig_length;
|
||||
|
||||
_test_setup();
|
||||
|
||||
/* Generate message signature with first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_sign_message(privkey_id, ECC_ALG, msg, sizeof(msg), signature, sizeof(signature), &sig_length));
|
||||
|
||||
/* Verify signature with public key of first keypair */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_verify_message(pubkey_id, ECC_ALG, msg,
|
||||
sizeof(msg), signature, sig_length));
|
||||
|
||||
_test_destroy_keys(0);
|
||||
|
||||
/* Signature and verification with deleted keys should fail */
|
||||
TEST_ASSERT_PSA_DOES_NOT_EXIST(psa_sign_message(privkey_id, ECC_ALG, msg, sizeof(msg),
|
||||
signature, sizeof(signature), &sig_length));
|
||||
TEST_ASSERT_PSA_DOES_NOT_EXIST(psa_verify_message(pubkey_id, ECC_ALG, msg, sizeof(msg),
|
||||
signature, sig_length));
|
||||
}
|
||||
|
||||
Test* tests_psa_persistent_asym_keypair_storage(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_psa_store_persistent_asym_keypair),
|
||||
new_TestFixture(test_psa_delete_persistent_asym_keypair),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(tests_psa_persistent_asym_keypair_storage_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&tests_psa_persistent_asym_keypair_storage_tests;
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Generate and use a persistently stored key in PSA Crypto
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "embUnit.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "tests_psa_persistent_storage.h"
|
||||
|
||||
#define PLAINTEXT_LEN (32)
|
||||
#define ENCR_OUTPUT_SIZE (PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(PSA_KEY_TYPE_AES, \
|
||||
PSA_ALG_CBC_NO_PADDING, \
|
||||
PLAINTEXT_LEN))
|
||||
|
||||
static uint8_t PLAINTEXT[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
|
||||
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
|
||||
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
|
||||
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
|
||||
};
|
||||
|
||||
static psa_key_id_t key_id_1 = 1;
|
||||
static psa_key_id_t key_id_2 = 2;
|
||||
|
||||
static void _test_setup(void)
|
||||
{
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
|
||||
psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
|
||||
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_usage_flags(&attr, usage);
|
||||
psa_set_key_bits(&attr, 128);
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_id(&attr, key_id_1);
|
||||
|
||||
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION
|
||||
(PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LOCATION_LOCAL_STORAGE);
|
||||
psa_set_key_lifetime(&attr, lifetime);
|
||||
|
||||
/* Import persistent key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_import_key(&attr, KEY_128, AES_128_KEY_SIZE, &key_id_1));
|
||||
|
||||
/* Import second key to overwrite the first one */
|
||||
psa_set_key_id(&attr, key_id_2);
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_import_key(&attr, OVERWRITE_KEY_128, AES_128_KEY_SIZE,
|
||||
&key_id_2));
|
||||
}
|
||||
|
||||
static void _test_destroy_keys(void)
|
||||
{
|
||||
/* Destroy first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(key_id_1));
|
||||
|
||||
/* Destroy second key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(key_id_2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A persistently stored key should still be accessible after
|
||||
* overwriting it in local memory
|
||||
*/
|
||||
static void test_psa_store_single_persistent_key(void)
|
||||
{
|
||||
uint8_t cipher_out[ENCR_OUTPUT_SIZE];
|
||||
uint8_t plain_out[PLAINTEXT_LEN];
|
||||
size_t output_len = 0;
|
||||
|
||||
_test_setup();
|
||||
|
||||
/* Generate cipher with first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_encrypt(key_id_1, PSA_ALG_CBC_NO_PADDING, PLAINTEXT,
|
||||
PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE, &output_len));
|
||||
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_decrypt(key_id_1, PSA_ALG_CBC_NO_PADDING, cipher_out,
|
||||
sizeof(cipher_out), plain_out, sizeof(plain_out), &output_len));
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(plain_out, PLAINTEXT, PLAINTEXT_LEN),
|
||||
"first key, wrong plaintext");
|
||||
|
||||
/* Generate cipher with second key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_encrypt(key_id_2, PSA_ALG_CBC_NO_PADDING, PLAINTEXT,
|
||||
PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE, &output_len));
|
||||
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_decrypt(key_id_2, PSA_ALG_CBC_NO_PADDING, cipher_out,
|
||||
sizeof(cipher_out), plain_out, sizeof(plain_out), &output_len));
|
||||
TEST_ASSERT_MESSAGE(0 == memcmp(plain_out, PLAINTEXT, PLAINTEXT_LEN),
|
||||
"second key, wrong plaintext");
|
||||
|
||||
_test_destroy_keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief After destroying a persistent key, it should not be available anymore
|
||||
*/
|
||||
static void test_psa_delete_single_persistent_key(void)
|
||||
{
|
||||
uint8_t cipher_out[ENCR_OUTPUT_SIZE];
|
||||
size_t output_len = 0;
|
||||
|
||||
_test_setup();
|
||||
|
||||
/* Generate cipher with first key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_encrypt(key_id_1, PSA_ALG_CBC_NO_PADDING, PLAINTEXT,
|
||||
PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE, &output_len));
|
||||
/* Generate cipher with second key */
|
||||
TEST_ASSERT_PSA_SUCCESS(psa_cipher_encrypt(key_id_2, PSA_ALG_CBC_NO_PADDING, PLAINTEXT,
|
||||
PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE, &output_len));
|
||||
|
||||
_test_destroy_keys();
|
||||
|
||||
/* Encryption with deleted keys should fail */
|
||||
TEST_ASSERT_PSA_DOES_NOT_EXIST(psa_cipher_encrypt(key_id_1, PSA_ALG_CBC_NO_PADDING, PLAINTEXT,
|
||||
PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE, &output_len));
|
||||
TEST_ASSERT_PSA_DOES_NOT_EXIST(psa_cipher_encrypt(key_id_2, PSA_ALG_CBC_NO_PADDING,
|
||||
PLAINTEXT, PLAINTEXT_LEN, cipher_out, ENCR_OUTPUT_SIZE,
|
||||
&output_len));
|
||||
}
|
||||
|
||||
Test* tests_psa_persistent_single_key_storage(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_psa_store_single_persistent_key),
|
||||
new_TestFixture(test_psa_delete_single_persistent_key),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(tests_psa_persistent_single_key_storage_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&tests_psa_persistent_single_key_storage_tests;
|
||||
}
|
14
tests/sys/psa_crypto_persistent_storage/tests/01-run.py
Executable file
14
tests/sys/psa_crypto_persistent_storage/tests/01-run.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2023 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run_check_unittests
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run_check_unittests())
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
* @defgroup <name> <description>
|
||||
* @{
|
||||
*
|
||||
* @file tests_psa_cbor_enc_dec.h
|
||||
* @brief
|
||||
*
|
||||
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TESTS_PSA_PERSISTENT_STORAGE_H
|
||||
#define TESTS_PSA_PERSISTENT_STORAGE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "embUnit.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AES_128_KEY_SIZE (16)
|
||||
|
||||
#define TEST_ASSERT_PSA_SUCCESS(func_) TEST_ASSERT_MESSAGE(func_ == PSA_SUCCESS, \
|
||||
#func_ " failed");
|
||||
#define TEST_ASSERT_PSA_DOES_NOT_EXIST(func_) TEST_ASSERT_MESSAGE(func_ == \
|
||||
PSA_ERROR_DOES_NOT_EXIST, #func_ " failed");
|
||||
#define TEST_ASSERT_PSA_ALREADY_EXISTS(func_) TEST_ASSERT_MESSAGE(func_ == \
|
||||
PSA_ERROR_ALREADY_EXISTS, #func_ " failed");
|
||||
|
||||
#define AES_128_KEY_SIZE (16)
|
||||
|
||||
static const uint8_t KEY_128[AES_128_KEY_SIZE] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
|
||||
static const uint8_t OVERWRITE_KEY_128[AES_128_KEY_SIZE] = {
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
|
||||
};
|
||||
|
||||
Test* tests_psa_persistent_single_key_storage(void);
|
||||
Test* tests_psa_persistent_asym_keypair_storage(void);
|
||||
Test* tests_psa_fail_overwrite_existing_key(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TESTS_PSA_PERSISTENT_STORAGE_H */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user