Skip to content

Commit

Permalink
tests/sys: Add tests for PSA Crypto persistent key storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Einhornhool committed Nov 21, 2023
1 parent 3392b68 commit 07be2fa
Show file tree
Hide file tree
Showing 8 changed files with 484 additions and 0 deletions.
23 changes: 23 additions & 0 deletions tests/sys/psa_crypto_persistent_storage/Makefile
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions tests/sys/psa_crypto_persistent_storage/app.config.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CONFIG_MODULE_EMBUNIT=y

CONFIG_MODULE_PSA_CRYPTO=y
CONFIG_MODULE_PSA_PERSISTENT_STORAGE=y

CONFIG_MODULE_PSA_CIPHER=y
CONFIG_MODULE_PSA_CIPHER_AES_128_CBC=y

CONFIG_MODULE_PSA_ASYMMETRIC=y
CONFIG_MODULE_PSA_ASYMMETRIC_ECC_ED25519=y

CONFIG_PSA_SINGLE_KEY_COUNT=1
CONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT=1
33 changes: 33 additions & 0 deletions tests/sys/psa_crypto_persistent_storage/main.c
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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_id_t privkey_id = 3;
static psa_key_id_t pubkey_id = 4;
static psa_key_id_t overwrite_privkey_id = 5;
static const uint8_t msg[EDDSA_MESSAGE_SIZE] = { 0x0b };

/**
* @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;
uint8_t public_key[ECC_PUBLIC_KEY_SIZE];
size_t pubkey_length;
psa_key_attributes_t privkey_attr = psa_key_attributes_init();
psa_key_attributes_t 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));

/* 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));
}

/**
* @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;
/* Destroy first key */
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(privkey_id));

/* Destroy second key */
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(pubkey_id));

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

/* Destroy last key, just to clean up */
TEST_ASSERT_PSA_SUCCESS(psa_destroy_key(overwrite_privkey_id));
}

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;
}
Loading

0 comments on commit 07be2fa

Please sign in to comment.