Skip to content

Commit

Permalink
sys/psa_crypto: ed25519 private key {ex,im}port
Browse files Browse the repository at this point in the history
  • Loading branch information
mguetschow committed Apr 17, 2024
1 parent a9e7b44 commit 5f08f74
Show file tree
Hide file tree
Showing 11 changed files with 428 additions and 35 deletions.
12 changes: 12 additions & 0 deletions pkg/c25519/psa_c25519/edsign.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ psa_status_t psa_generate_ecc_ed25519_key_pair( uint8_t *priv_key_buffer, uint8_
return PSA_SUCCESS;
}

psa_status_t psa_derive_ecc_ed25519_public_key( const uint8_t *priv_key_buffer, uint8_t *pub_key_buffer,

Check warning on line 39 in pkg/c25519/psa_c25519/edsign.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
size_t priv_key_buffer_length,
size_t *pub_key_buffer_length)
{
*pub_key_buffer_length = EDSIGN_PUBLIC_KEY_SIZE;

edsign_sec_to_pub(pub_key_buffer, priv_key_buffer);

(void)priv_key_buffer_length;
return PSA_SUCCESS;
}

psa_status_t psa_ecc_ed25519_sign_message( const uint8_t *priv_key_buffer,
size_t priv_key_buffer_size,
const uint8_t *pub_key_buffer,
Expand Down
27 changes: 27 additions & 0 deletions pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ psa_status_t psa_generate_ecc_ed25519_key_pair( uint8_t *priv_key_buffer,
return CRYS_to_psa_error(ret);
}

psa_status_t psa_derive_ecc_ed25519_public_key( const uint8_t *priv_key_buffer, uint8_t *pub_key_buffer,

Check warning on line 63 in pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
size_t priv_key_buffer_length,
size_t *pub_key_buffer_length)
{
CRYS_ECEDW_TempBuff_t tmp;
CRYSError_t ret;

/* contains seed (private key), concatenated with public key */
uint8_t secret_key[CRYS_ECEDW_ORD_SIZE_IN_BYTES + CRYS_ECEDW_MOD_SIZE_IN_BYTES] = { 0x0 };
size_t secret_key_size = sizeof(secret_key);

*pub_key_buffer_length = CRYS_ECEDW_MOD_SIZE_IN_BYTES;

cryptocell_310_enable();
ret = CRYS_ECEDW_SeedKeyPair(priv_key_buffer, priv_key_buffer_length, secret_key, &secret_key_size,

Check warning on line 77 in pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
pub_key_buffer, pub_key_buffer_length, &tmp);
cryptocell_310_disable();
if (ret != CRYS_OK) {
DEBUG("CRYS_ECEDW_SeedKeyPair failed with %s\n", cryptocell310_status_to_humanly_readable(ret));

Check warning on line 81 in pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
goto done;
}

done:
explicit_bzero(&secret_key, sizeof(secret_key));
return CRYS_to_psa_error(ret);
}

psa_status_t psa_ecc_ed25519_sign_message(const uint8_t *priv_key_buffer,
size_t priv_key_buffer_size,
const uint8_t *pub_key_buffer,
Expand Down
48 changes: 41 additions & 7 deletions sys/include/psa_crypto/psa/crypto_sizes.h
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,22 @@ extern "C" {
#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \
/* implementation-defined value */

/**
* @brief Maximum size of the export encoding of an ECC keypair.
*
* @details The representation of an ECC keypair follows
* https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html#key-formats
* and is dependent on the family:
* - for twisted Edwards curves: 32B
* - for Weierstrass curves: `ceiling(m/8)`-byte string, big-endian
* where m is the bit size associated with the curve.
*/
#define PSA_KEY_EXPORT_ECC_KEY_MAX_SIZE(key_type, key_bits) \
(size_t)\
(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) == PSA_ECC_FAMILY_TWISTED_EDWARDS ? 32 : \
(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) == PSA_ECC_FAMILY_SECP_R1 ? PSA_BITS_TO_BYTES(key_bits) : \

Check warning on line 807 in sys/include/psa_crypto/psa/crypto_sizes.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
0))

/**
* @brief Sufficient output buffer size for @ref psa_export_key().
*
Expand Down Expand Up @@ -828,7 +844,9 @@ extern "C" {
* Unspecified if the parameters are not valid.
*/
#define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \
/* implementation-defined value */
(PSA_KEY_TYPE_IS_PUBLIC_KEY(key_type) ? PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) : \

Check warning on line 847 in sys/include/psa_crypto/psa/crypto_sizes.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
(PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_KEY_MAX_SIZE(key_type, key_bits) : \
0))

/**
* @brief Check whether the key size is a valid ECC size for key type.
Expand Down Expand Up @@ -861,7 +879,19 @@ extern "C" {
*
* See also @ref PSA_EXPORT_KEY_OUTPUT_SIZE().
*/
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE /* implementation-defined value */
#if (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P256R1) || \
IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A_ECC_P256))
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
(PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_ECC_FAMILY_SECT_R1, 256))
#elif (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_ED25519))
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
(PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_ECC_FAMILY_TWISTED_EDWARDS, 255))
#elif (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P192R1))
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \
(PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_ECC_FAMILY_SECT_R1, 192))
#else
#define PSA_EXPORT_KEY_PAIR_MAX_SIZE 0
#endif

/**
* @brief Get curve size from ECC public key
Expand Down Expand Up @@ -958,13 +988,17 @@ extern "C" {
* See also @ref PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(@p key_type, @p key_bits).
*/
#if (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P256R1) || \
IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P192R1) || \
IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A_ECC_P256))
IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A_ECC_P256))
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_ECC_FAMILY_SECT_R1, PSA_MAX_PRIV_KEY_SIZE))
#else
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_ECC_FAMILY_SECT_R1, 256))
#elif (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P192R1))
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_ECC_FAMILY_SECT_R1, 192))
#elif (IS_USED(MODULE_PSA_ASYMMETRIC_ECC_ED25519))
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_ECC_FAMILY_TWISTED_EDWARDS, PSA_MAX_PRIV_KEY_SIZE))
(PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_ECC_FAMILY_TWISTED_EDWARDS, 255))
#else
#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE 0
#endif

/**
Expand Down
15 changes: 15 additions & 0 deletions sys/psa_crypto/include/psa_crypto_algorithm_dispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,21 @@ psa_status_t psa_algorithm_dispatch_verify_message( const psa_key_attributes_t *
*/
psa_status_t psa_algorithm_dispatch_generate_key( const psa_key_attributes_t *attributes,
psa_key_slot_t *slot);

/**
* @brief Dispatch the key import function to a specific backend.
* See psa_import_key()
*
* @param attributes
* @param data
* @param data_length
* @param slot
* @param bits
* @return psa_status_t
*/
psa_status_t psa_algorithm_dispatch_import_key(const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
psa_key_slot_t *slot, size_t *bits);
#endif

#if IS_USED(MODULE_PSA_CIPHER)
Expand Down
13 changes: 13 additions & 0 deletions sys/psa_crypto/include/psa_ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,19 @@ psa_status_t psa_generate_ecc_ed25519_key_pair( uint8_t *priv_key_buffer, uint8_
size_t *priv_key_buffer_length,
size_t *pub_key_buffer_length);

/**
* @brief Low level wrapper function to call a driver for deriving an ed25519 public key from the private key.
*
* @param[in] priv_key_buffer
* @param[out] pub_key_buffer
* @param[in] priv_key_buffer_length
* @param[inout] pub_key_buffer_length
* @return @ref psa_status_t
*/
psa_status_t psa_derive_ecc_ed25519_public_key( const uint8_t *priv_key_buffer, uint8_t *pub_key_buffer,
size_t priv_key_buffer_length,
size_t *pub_key_buffer_length);

/**
* @brief Low level wrapper function to call a driver for an ECC hash signature
* with an ed25519 key.
Expand Down
102 changes: 93 additions & 9 deletions sys/psa_crypto/psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1220,16 +1220,102 @@ psa_status_t psa_destroy_key(psa_key_id_t key)
return psa_wipe_key_slot(slot);
}

/**
* @brief Export key that is stored in local memory
*
* See @ref psa_export_key
*
* @param key_buffer
* @param key_buffer_size
* @param data
* @param data_size
* @param data_length
*
* @return @ref PSA_SUCCESS
* @ref PSA_ERROR_INVALID_ARGUMENT
*/
static psa_status_t psa_builtin_export_key(const uint8_t *key_buffer,
size_t key_buffer_size,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
if (!key_buffer || !data || !data_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}

if (key_buffer_size == 0 || data_size == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}

if (data_size < key_buffer_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, key_buffer, key_buffer_size);
*data_length = key_buffer_size;

return PSA_SUCCESS;
}

psa_status_t psa_export_key(psa_key_id_t key,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
(void)key;
(void)data;
(void)data_size;
(void)data_length;
return PSA_ERROR_NOT_SUPPORTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
uint8_t *privkey_data = NULL;
size_t *privkey_data_len = NULL;

if (!lib_initialized) {
return PSA_ERROR_BAD_STATE;
}

if (!data || !data_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}

*data_length = 0;

status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_EXPORT, 0);
if (status != PSA_SUCCESS) {
unlock_status = psa_unlock_key_slot(slot);
if (unlock_status != PSA_SUCCESS) {
status = unlock_status;
}
return status;
}

psa_key_lifetime_t lifetime = psa_get_key_lifetime(&slot->attr);
if (psa_key_lifetime_is_external(lifetime)) {
/* key export from an external device is currently not supported */
status = PSA_ERROR_NOT_SUPPORTED;
unlock_status = psa_unlock_key_slot(slot);
if (unlock_status != PSA_SUCCESS) {
status = unlock_status;
}
return status;
}

if (!PSA_KEY_TYPE_IS_ECC(slot->attr.type) ||
PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type) != PSA_ECC_FAMILY_TWISTED_EDWARDS) {
/* key export is currently only supported for ed25519 keys */
status = PSA_ERROR_NOT_SUPPORTED;
unlock_status = psa_unlock_key_slot(slot);
if (unlock_status != PSA_SUCCESS) {
status = unlock_status;
}
return status;
}

psa_get_key_data_from_key_slot(slot, &privkey_data, &privkey_data_len);

status =
psa_builtin_export_key(privkey_data, *privkey_data_len, data, data_size, data_length);

unlock_status = psa_unlock_key_slot(slot);
return ((status == PSA_SUCCESS) ? unlock_status : status);
}

/**
Expand Down Expand Up @@ -1260,10 +1346,6 @@ static psa_status_t psa_builtin_export_public_key( const uint8_t *key_buffer,
DEBUG("PSA Crypto Builtin Export Key: Output buffer too small\n");
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/** Some implementations and drivers can generate a public key from existing private key
* material. This implementation does not support the recalculation of a public key, yet.
* It requires the key to already exist in local memory and just copies it into the data
* output. */
memcpy(data, key_buffer, key_buffer_size);
*data_length = key_buffer_size;

Expand Down Expand Up @@ -1456,8 +1538,10 @@ psa_status_t psa_builtin_import_key(const psa_key_attributes_t *attributes,
if (data_length > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) {
return PSA_ERROR_NOT_SUPPORTED;
}

memcpy(key_buffer, data, data_length);
*key_buffer_length = data_length;

return PSA_SUCCESS;
}
return status;
Expand Down
67 changes: 67 additions & 0 deletions sys/psa_crypto/psa_crypto_algorithm_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,73 @@ psa_status_t psa_algorithm_dispatch_generate_key( const psa_key_attributes_t *

return psa_builtin_generate_key(attributes, key_data, *key_bytes, key_bytes);
}

psa_status_t psa_algorithm_dispatch_import_key(const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
psa_key_slot_t *slot, size_t *bits)
{
uint8_t *key_data = NULL;
size_t *key_bytes = NULL;
size_t key_data_size;

key_data_size = psa_get_key_data_from_key_slot(slot, &key_data, &key_bytes);

/**
* Asymmetric keys needs special import handling:
* The public key needs to be derived from the imported private key.
*/
if (PSA_KEY_TYPE_IS_KEY_PAIR(attributes->type)) {
psa_asym_key_t asym_key = PSA_INVALID_OPERATION;
uint8_t *pubkey_data = NULL;
size_t *pubkey_data_len = NULL;
psa_get_public_key_data_from_key_slot(slot, &pubkey_data, &pubkey_data_len);

if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type)) {
asym_key =
PSA_ENCODE_ECC_KEY_TYPE(attributes->bits,
PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type));

if (asym_key == PSA_INVALID_OPERATION) {
return PSA_ERROR_INVALID_ARGUMENT;
}
}

// derive and save public from private key
psa_status_t ret = PSA_ERROR_NOT_SUPPORTED;
switch (asym_key) {
#if IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P192R1)
case PSA_ECC_P192_R1:
// todo: support for Weierstrass curves
(void)slot;
ret = PSA_ERROR_NOT_SUPPORTED;
break;
#endif
#if IS_USED(MODULE_PSA_ASYMMETRIC_ECC_P256R1)
case PSA_ECC_P256_R1:
// todo: support for Weierstrass curves
(void)slot;
ret = PSA_ERROR_NOT_SUPPORTED;
break;
#endif
#if IS_USED(MODULE_PSA_ASYMMETRIC_ECC_ED25519)
case PSA_ECC_ED25519:
ret = psa_derive_ecc_ed25519_public_key(data, pubkey_data, data_length, pubkey_data_len);
break;
#endif
default:
(void)slot;
ret = PSA_ERROR_NOT_SUPPORTED;
break;
}
if (ret == PSA_SUCCESS) {
/* save private key data */
memcpy(key_data, data, data_length);
*key_bytes = data_length;
}
return ret;
}
return psa_builtin_import_key(attributes, data, data_length, key_data, key_data_size, key_bytes, bits);
}
#endif /* MODULE_PSA_KEY_MANAGEMENT */

#if IS_USED(MODULE_PSA_CIPHER)
Expand Down
Loading

0 comments on commit 5f08f74

Please sign in to comment.