Skip to content

Commit

Permalink
sys/psa_crypto: implement persistent key storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Einhornhool committed Nov 21, 2023
1 parent e51dc09 commit 3392b68
Show file tree
Hide file tree
Showing 15 changed files with 1,231 additions and 92 deletions.
1 change: 1 addition & 0 deletions sys/psa_crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ rsource "Kconfig.keys"

rsource "psa_se_mgmt/Kconfig"
rsource "psa_key_slot_mgmt/Kconfig"
rsource "psa_persistent_storage/Kconfig"

endif # MODULE_PSA_CRYPTO
4 changes: 4 additions & 0 deletions sys/psa_crypto/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions sys/psa_crypto/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ ifneq (,$(filter psa_crypto,$(USEMODULE)))
USEMODULE += prng_musl_lcg
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_slot_mgmt
Expand Down
9 changes: 7 additions & 2 deletions sys/psa_crypto/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@
* 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`
*
* #### Lifetime Encoding
* When creating a key, the user needs to specify a lifetime value, which actually consists
Expand Down Expand Up @@ -233,6 +235,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
*
Expand Down
124 changes: 124 additions & 0 deletions sys/psa_crypto/include/psa_crypto_cbor_encoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* 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 Encodes a basic key slot in CBOR
*
* Single Key Format:
* - Key Slot Array:
* - Attributes Array[5]:
* - ID (First bytes are always ID for quick lookup)
* - Type
* - Bits
* - Lifetime
* - Policy Array[2]:
* - Usage
* - Algorithm
* - Key Array[2]
* - Key Length
* - Key Data Array[slot->key.data_len]
* - Key Data
*
* Asymmetric Key Pair Format:
* - Key Slot Array:
* - Attributes Array[5]:
* - ID (First bytes are always ID for quick lookup)
* - Type
* - Bits
* - Lifetime
* - Policy Array[2]:
* - Usage
* - Algorithm
* - Key Pair Array[2]:
* - Private Key Array[2]
* - Private Key Data Length
* - Private Key Data Array[slot->key.data_len]
* - Private Key Data
* - Public Key Array[2]
* - Public Key Length
* - Public Key Array[pubkey_data_len]
* - Public Key Data
*
* Protected Key Format:
* - Key Slot Array:
* - ID (First bytes are always ID for quick lookup)
* - Type
* - Bits
* - Lifetime
* - Policy Array[2]:
* - Usage
* - Algorithm
* - Prot Key Array[1-2]
* - Key Slot Number
* *optional:*
* - Public Key Array[2]
* - Public Key Len
* - Public Key Array[pubkey_data_len]
* - Public Key Data
*
* @param slot Pointer to slot containing the key to encode
* @param output Buffer to write the encoded key to
* @param output_len Length of output buffer
* @param 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 */
/** @} */
69 changes: 69 additions & 0 deletions sys/psa_crypto/include/psa_crypto_persistent_storage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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 cbor_buf Pointer to CBOR encoded data
* @param cbor_buf_len Length of CBOR encoded data
* @return psa_status_t
*/
psa_status_t psa_write_cbor_encoded_key_slot_to_file(psa_key_id_t id,
uint8_t* cbor_buf,
size_t cbor_buf_len);

/**
* @brief Reads a CBOR encoded key slot from a file
*
* @param id ID of the desired key
* @param cbor_buf Output buffer to write CBOR data to
* @param cbor_buf_size Size of output buffer
* @param cbor_data_len Actual length of CBOR encoded data
* @return psa_status_t
*/
psa_status_t psa_get_cbor_encoded_key_slot_from_file(psa_key_id_t id,
uint8_t *cbor_buf,
size_t cbor_buf_size,
size_t *cbor_data_len);

/**
* @brief Destroy a key in persistent storage
*
* @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 */
/** @} */
53 changes: 53 additions & 0 deletions sys/psa_crypto/include/psa_crypto_slot_management.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,51 @@ typedef struct {
} key; /**< Key data structure */
} psa_key_slot_t;

#if IS_USED(MODULE_PSA_SECURE_ELEMENT) || IS_USED(MODULE_EMBUNIT)
/**
* @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_SECURE_ELEMENT_ASYMMETRIC) || IS_USED(MODULE_EMBUNIT)
uint8_t pubkey_data[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
size_t pubkey_data_len;
#endif
} key;
} psa_prot_key_slot_t;
#endif /* MODULE_PSA_SECURE_ELEMENT_ASYMMETRIC */

#if IS_USED(MODULE_PSA_ASYMMETRIC)
/**
* @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 /* MODULE_PSA_ASYMMETRIC */

/**
* @brief Initializes the allocated key slots and prepares the internal key slot lists.
*/
Expand Down Expand Up @@ -163,6 +208,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.
*
Expand Down
Loading

0 comments on commit 3392b68

Please sign in to comment.