Skip to content

Commit

Permalink
nrf_security: cracen: Add support for ED25519PH
Browse files Browse the repository at this point in the history
Adding ED25519PH to the supported algorithms for cracen
Updated logic for selecting which algorithm to use cracen
key_management.c to handle different algorithms using
same curve and key_bits

Signed-off-by: Dag Erik Gjørvad <[email protected]>
  • Loading branch information
degjorva authored and nordicjm committed Dec 20, 2024
1 parent dee077d commit 9e4cd47
Show file tree
Hide file tree
Showing 9 changed files with 590 additions and 18 deletions.
1 change: 1 addition & 0 deletions subsys/nrf_security/cmake/psa_crypto_config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ED25519PH)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_RSA_PSS)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_ECC)
kconfig_check_and_set_base_to_one(PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_RSA)
Expand Down
1 change: 1 addition & 0 deletions subsys/nrf_security/configs/psa_crypto_config.h.template
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
#cmakedefine PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255 @PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_255@
#cmakedefine PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448 @PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448@
#cmakedefine PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS @PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS@
#cmakedefine PSA_NEED_CRACEN_ED25519PH @PSA_NEED_CRACEN_ED25519PH@
#cmakedefine PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN @PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN@
#cmakedefine PSA_NEED_CRACEN_RSA_PSS @PSA_NEED_CRACEN_RSA_PSS@
#cmakedefine PSA_NEED_CRACEN_RSA_OAEP @PSA_NEED_CRACEN_RSA_OAEP@
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <sicrypto/ecc.h>
#include <sicrypto/ecdsa.h>
#include <sicrypto/ed25519.h>
#include <sicrypto/ed25519ph.h>
#include <sicrypto/ed448.h>
#include <sicrypto/montgomery.h>
#include <sicrypto/rsa_keygen.h>
Expand Down Expand Up @@ -602,6 +603,7 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_
psa_status_t psa_status;
size_t expected_pub_key_size = 0;
int si_status = 0;
psa_algorithm_t key_alg = psa_get_key_algorithm(attributes);
const struct sx_pk_ecurve *sx_curve;
struct sitask t;

Expand Down Expand Up @@ -673,9 +675,15 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_
break;
case PSA_ECC_FAMILY_TWISTED_EDWARDS:
if (key_bits_attr == 255) {
priv_key.def = si_sig_def_ed25519;
priv_key.key.ed25519 = (struct sx_ed25519_v *)key_buffer;
pub_key.key.ed25519 = (struct sx_ed25519_pt *)data;
if (key_alg == PSA_ALG_ED25519PH) {
priv_key.def = si_sig_def_ed25519ph;
priv_key.key.ed25519 = (struct sx_ed25519_v *)key_buffer;
pub_key.key.ed25519 = (struct sx_ed25519_pt *)data;
} else {
priv_key.def = si_sig_def_ed25519;
priv_key.key.ed25519 = (struct sx_ed25519_v *)key_buffer;
pub_key.key.ed25519 = (struct sx_ed25519_pt *)data;
}
} else {
priv_key.def = si_sig_def_ed448;
priv_key.key.ed448 = (struct sx_ed448_v *)key_buffer;
Expand All @@ -700,6 +708,7 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_
*data_length = expected_pub_key_size;
return PSA_SUCCESS;
}

static psa_status_t export_rsa_public_key_from_keypair(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size, uint8_t *data,
Expand Down
24 changes: 23 additions & 1 deletion subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum kmu_metadata_algorithm {
METADATA_ALG_CMAC = 9,
METADATA_ALG_ED25519 = 10,
METADATA_ALG_ECDSA = 11,
METADATA_ALG_RESERVED2 = 12,
METADATA_ALG_ED25519PH = 12,
METADATA_ALG_RESERVED3 = 13,
METADATA_ALG_RESERVED4 = 14,
METADATA_ALG_RESERVED5 = 15,
Expand Down Expand Up @@ -463,6 +463,15 @@ static psa_status_t convert_to_psa_attributes(kmu_metadata *metadata,
: PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
psa_set_key_algorithm(key_attr, PSA_ALG_PURE_EDDSA);
break;
case METADATA_ALG_ED25519PH:
/* If the key can sign it is assumed it is a private key */
psa_set_key_type(
key_attr,
can_sign(key_attr)
? PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS)
: PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
psa_set_key_algorithm(key_attr, PSA_ALG_ED25519PH);
break;
case METADATA_ALG_ECDSA:
psa_set_key_type(key_attr,
can_sign(key_attr)
Expand Down Expand Up @@ -614,6 +623,19 @@ psa_status_t convert_from_psa_attributes(const psa_key_attributes_t *key_attr,
metadata->algorithm = METADATA_ALG_ED25519;
break;

case PSA_ALG_ED25519PH:
if (PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(key_attr)) !=
PSA_ECC_FAMILY_TWISTED_EDWARDS) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* Don't support private keys that are only used for verify */
if (!can_sign(key_attr) &&
PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_get_key_type(key_attr))) {
return PSA_ERROR_NOT_SUPPORTED;
}
metadata->algorithm = METADATA_ALG_ED25519PH;
break;

case PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):
if (PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(key_attr)) !=
PSA_ECC_FAMILY_SECP_R1) {
Expand Down
98 changes: 84 additions & 14 deletions subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sicrypto/drbghash.h>
#include <sicrypto/ecdsa.h>
#include <sicrypto/ed25519.h>
#include <sicrypto/ed25519ph.h>
#include <sicrypto/ik.h>
#include <sicrypto/internal.h>
#include <sicrypto/rsapss.h>
Expand Down Expand Up @@ -127,6 +128,19 @@ static int cracen_signature_prepare_ec_prvkey(struct si_sig_privkey *privkey, ch
}
}

if (IS_ENABLED(PSA_NEED_CRACEN_ED25519PH)) {
if (alg == PSA_ALG_ED25519PH) {
privkey->def = si_sig_def_ed25519ph;
privkey->key.ed25519 = (struct sx_ed25519_v *)key_buffer;
if (message) {
return cracen_signature_set_hashalgo(&privkey->hashalg, alg);
} else {
return cracen_signature_set_hashalgo_from_digestsz(
&privkey->hashalg, alg, digestsz);
}
}
}

if (IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_R1) ||
IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_K1) ||
IS_ENABLED(PSA_NEED_CRACEN_ECDSA_BRAINPOOL_P_R1)) {
Expand Down Expand Up @@ -210,6 +224,25 @@ static int cracen_signature_prepare_ec_pubkey(struct sitask *t, struct si_sig_pu
}
}

if (IS_ENABLED(PSA_NEED_CRACEN_ED25519PH) && alg == PSA_ALG_ED25519PH) {
pubkey->def = si_sig_def_ed25519ph;
if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(psa_get_key_type(attributes))) {
pubkey->key.ed25519 = (struct sx_ed25519_pt *)key_buffer;
if (message) {
cracen_signature_set_hashalgo(&pubkey->hashalg,
alg);
} else {
cracen_signature_set_hashalgo_from_digestsz(&pubkey->hashalg,
alg, digestsz);
}
return SX_OK;
}
if (curvesz != key_buffer_size) {
return SX_ERR_INVALID_KEY_SZ;
}
pubkey->key.ed25519 = (struct sx_ed25519_pt *)pubkey_buffer;
}

if (IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_R1) ||
IS_ENABLED(PSA_NEED_CRACEN_ECDSA_SECP_K1) ||
IS_ENABLED(PSA_NEED_CRACEN_ECDSA_BRAINPOOL_P_R1)) {
Expand Down Expand Up @@ -280,7 +313,7 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu
return silex_statuscodes_to_psa(SX_ERR_INCOMPATIBLE_HW);
}

if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA) {
if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA && alg != PSA_ALG_ED25519PH) {
return PSA_ERROR_INVALID_ARGUMENT;
}

Expand All @@ -306,14 +339,34 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu
sign.r = (char *)signature;
sign.s = (char *)signature + *signature_length / 2;

if (message) {
/* ED25519PH requires prehashing and supports sign and verify message
* the message is therefore hashed here before si_sig_verify is called
*/
if (alg == PSA_ALG_ED25519PH && message) {
uint8_t status;
uint8_t hash[64];
size_t output_len;

status = psa_hash_compute(PSA_ALG_SHA_512,
input, input_length, hash,
sizeof(hash), &output_len);
if (status != PSA_SUCCESS) {
return status;
}

si_sig_create_sign(&t, &privkey, &sign);
si_task_consume(&t, (char *)input, input_length);
si_task_consume(&t, (char *)hash, sizeof(hash));
} else {
si_sig_create_sign_digest(&t, &privkey, &sign);
si_task_consume(&t, (char *)input, sx_hash_get_alg_digestsz(privkey.hashalg));
}
if (message) {
si_sig_create_sign(&t, &privkey, &sign);
} else {
si_sig_create_sign_digest(&t, &privkey, &sign);

}
si_task_consume(&t, (char *)input,
message ? input_length : sx_hash_get_alg_digestsz(privkey.hashalg));

}
si_task_run(&t);
si_status = si_task_wait(&t);
safe_memzero(workmem, sizeof(workmem));
Expand Down Expand Up @@ -342,7 +395,7 @@ static psa_status_t cracen_signature_ecc_verify(int message, const psa_key_attri
return silex_statuscodes_to_psa(SX_ERR_INCOMPATIBLE_HW);
}

if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA) {
if (!PSA_ALG_IS_ECDSA(alg) && alg != PSA_ALG_PURE_EDDSA && !PSA_ALG_IS_HASH_EDDSA(alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}

Expand All @@ -366,20 +419,37 @@ static psa_status_t cracen_signature_ecc_verify(int message, const psa_key_attri
sign.sz = signature_length;
sign.r = (char *)signature;
sign.s = (char *)signature + signature_length / 2;
/* ED25519PH requires prehashing and supports sign and verify message
* the message is therefore hashed here before si_sig_verify is called
*/
if (alg == PSA_ALG_ED25519PH && message) {
psa_status_t status;
uint8_t hash[64];
uint32_t output_len;

status = psa_hash_compute(PSA_ALG_SHA_512,
input, input_length, hash,
sizeof(hash), &output_len);
if (status != PSA_SUCCESS) {
return status;
}

if (message) {
si_sig_create_verify(&t, &pubkey, &sign);
si_task_consume(&t, (char *)hash, sizeof(hash));
} else {
if (sx_hash_get_alg_digestsz(pubkey.hashalg) != input_length) {
return PSA_ERROR_INVALID_ARGUMENT;
if (message) {
si_sig_create_verify(&t, &pubkey, &sign);
} else {
if (sx_hash_get_alg_digestsz(pubkey.hashalg) != input_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
si_sig_create_verify_digest(&t, &pubkey, &sign);
}
si_sig_create_verify_digest(&t, &pubkey, &sign);
}

si_task_consume(&t, (char *)input, input_length);
si_task_consume(&t, (char *)input, input_length);
}
si_task_run(&t);
si_status = si_task_wait(&t);

safe_memzero(workmem, sizeof(workmem));
return silex_statuscodes_to_psa(si_status);
}
Expand Down
9 changes: 9 additions & 0 deletions subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,14 @@ config PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS_448
depends on PSA_WANT_ECC_TWISTED_EDWARDS_448
depends on PSA_USE_CRACEN_ASYMMETRIC_DRIVER

config PSA_NEED_CRACEN_ED25519PH
bool
default y
select PSA_ACCEL_ED25519PH
depends on PSA_WANT_ALG_ED25519PH
depends on PSA_WANT_ECC_TWISTED_EDWARDS_255
depends on PSA_USE_CRACEN_ASYMMETRIC_DRIVER

config PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS
bool
default y
Expand All @@ -376,6 +384,7 @@ config PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_ANY_ECC
depends on PSA_NEED_CRACEN_ECDSA_BRAINPOOL_P_R1 || \
PSA_NEED_CRACEN_ECDSA_SECP_R1 || \
PSA_NEED_CRACEN_ECDSA_SECP_K1 || \
PSA_NEED_CRACEN_ED25519PH || \
PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS

config PSA_NEED_CRACEN_RSA_PKCS1V15_SIGN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/** Ed25519 signature-related operations.
*
* @file
*
* @copyright Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef SICRYPTO_ED25519PH_HEADER_FILE
#define SICRYPTO_ED25519PH_HEADER_FILE

#ifdef __cplusplus
extern "C" {
#endif

#include "sig.h"

/** Signature definitions for ED25519PH keys.
*
* The following constraints apply when using Ed25519ph keys:
*
* When generating a signature with si_sig_create_sign():
* - The task needs a workmem buffer of at least 160 bytes.
* - The message to be signed must be given with a single call to
* si_task_consume().
* - The buffer for private key material must be in DMA memory.
* - The signature buffer must be in DMA memory.
*
* When verifying a signature with si_sig_create_verify():
* - The task needs a workmem buffer of at least 64 bytes.
* - The buffer for public key material must be in DMA memory.
* - The signature buffer must be in DMA memory.
* - The task can use partial processing. For the first partial run, the sum of
* the sizes of the provided message chunks plus 64 must be a multiple of
* 128 bytes. For any other partial run, the sum of the sizes of the provided
* message chunks must be a multiple of 128 bytes.
*
* When computing a public key with si_sig_create_pubkey():
* - The task needs a workmem buffer of at least 64 bytes.
* - The buffer for private key material must be in DMA memory.
*/
extern const struct si_sig_def *const si_sig_def_ed25519ph;

#ifdef __cplusplus
}
#endif

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ list(APPEND cracen_driver_sources
${CMAKE_CURRENT_LIST_DIR}/src/ecc.c
${CMAKE_CURRENT_LIST_DIR}/src/ecdsa.c
${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c
${CMAKE_CURRENT_LIST_DIR}/src/ed25519ph.c
${CMAKE_CURRENT_LIST_DIR}/src/ed448.c
${CMAKE_CURRENT_LIST_DIR}/src/hash.c
${CMAKE_CURRENT_LIST_DIR}/src/hkdf.c
Expand Down
Loading

0 comments on commit 9e4cd47

Please sign in to comment.