diff --git a/subsys/nrf_security/Kconfig.psa.nordic b/subsys/nrf_security/Kconfig.psa.nordic index 21074e56208d..4aff153aee72 100644 --- a/subsys/nrf_security/Kconfig.psa.nordic +++ b/subsys/nrf_security/Kconfig.psa.nordic @@ -400,3 +400,10 @@ config PSA_WANT_KEY_TYPE_SRP_PUBLIC_KEY bool "SRP public key support" if !MBEDTLS_PROMPTLESS help SRP public key support. + +comment "Nordic added alternative cracen driver" + +config PSA_WANT_NO_SI_CRYPTO + bool "Running supported crypto operations without sicrypto" if !MBEDTLS_PROMPTLESS + help + Using alternative high level driver for cracen when supported diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake index d18cc88822d2..00ad5e186e0f 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake @@ -78,6 +78,12 @@ if(CONFIG_PSA_NEED_CRACEN_ECJPAKE_SECP_R1_256) ) endif() +if(CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519) + list(APPEND cracen_driver_sources + ${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c + ) +endif() + if(CONFIG_PSA_NEED_CRACEN_SRP_6) list(APPEND cracen_driver_sources ${CMAKE_CURRENT_LIST_DIR}/src/srp.c diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h index 1719f9e675d8..066d1ca99b87 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h @@ -361,4 +361,13 @@ psa_status_t cracen_spake2p_get_shared_key(cracen_spake2p_operation_t *operation psa_status_t cracen_spake2p_abort(cracen_spake2p_operation_t *operation); +int ed25519_sign(const uint8_t *ed25519, char *signature, + const uint8_t *message); + +int ed25519_verify(const uint8_t *pubkey, const char *message, + size_t message_length, const char *signature); + +int create_ed25519_pubkey(const uint8_t *ed25519, + uint8_t *pubkey); + #endif /* CRACEN_PSA_H */ diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed25519.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed25519.c new file mode 100644 index 000000000000..9a21ab30200b --- /dev/null +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed25519.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ +#include +#include +#include +#include +#include +#include + +int ed25519_sign(const uint8_t *ed25519, char *signature, const uint8_t *message) +{ + char workmem[160]; + struct sxhash hashopctx; + char pointr_buffer[64]; + char *pointr = pointr_buffer; + int r; + + /*Hash the private key, the digest is stored in the first 64 bytes of workmem*/ + r = sx_hash_create(&hashopctx, &sxhashalg_sha2_512, sizeof(hashopctx)); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, ed25519, 32); + if (r != 0) { + return r; + } + r = sx_hash_digest(&hashopctx, workmem); + if (r != 0) { + return r; + } + /*Wait to make sure hash operation is finished before doing calculations on it*/ + r = sx_hash_wait(&hashopctx); + if (r != 0) { + return r; + } + /* Obtain r by hashing (prefix || message), where prefix is the second + * half of the private key digest. + */ + + r = sx_hash_create(&hashopctx, &sxhashalg_sha2_512, sizeof(hashopctx)); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, workmem+32, 32); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, message, 100); + if (r != 0) { + return r; + } + r = sx_hash_digest(&hashopctx, workmem+96); + if (r != 0) { + return r; + } + + /* Perform point multiplication R = [r]B. This is the encoded point R, + * which is the first part of the signature. + */ + r = sx_ed25519_ptmult((const struct sx_ed25519_dgst *)(workmem + 96), + (struct sx_ed25519_pt *)pointr); + if (r != 0) { + return r; + + } + /* The secret scalar s is computed in place from the first half of the + * private key digest. + */ + decode_scalar_25519(workmem); + + /* Clear second half of private key digest: sx_async_ed25519_ptmult_go() + * works on an input of SX_ED25519_DGST_SZ bytes. + */ + safe_memset(workmem + 32, 128, 0, 32); + + /* Perform point multiplication A = [s]B, to obtain the public key A. + * Which is stored in workmem[32:63] + */ + r = sx_ed25519_ptmult((const struct sx_ed25519_dgst *)(workmem), + (struct sx_ed25519_pt *)(struct sx_ed25519_pt *)((char *)workmem + 32)); + if (r != 0) { + return r; + } + + /* Obtain k by hashing (R || A || message). */ + r = sx_hash_create(&hashopctx, &sxhashalg_sha2_512, sizeof(hashopctx)); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, pointr, 32); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, workmem+32, 32); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, message, 100); + if (r != 0) { + return r; + } + r = sx_hash_digest(&hashopctx, workmem+32); + if (r != 0) { + return r; + } + + /* Compute (r + k * s) mod L. This gives the second part of the + * signature, which is the encoded S which is stored in pointr. + */ + + r = sx_ed25519_sign( + (const struct sx_ed25519_dgst *)(workmem + 32), + (const struct sx_ed25519_dgst *)(workmem + 3 * 32), + (const struct sx_ed25519_v *)workmem, + (struct sx_ed25519_v *)(pointr + SX_ED25519_PT_SZ)); + if (r != 0) { + return r; + } + + memcpy(signature, pointr, 64); + + return r; +} + +int ed25519_verify(const uint8_t *pubkey, const char *message, + size_t message_length, const char *signature) +{ + + char workmem[64]; + struct sxhash hashopctx; + int r; + + + r = sx_hash_create(&hashopctx, &sxhashalg_sha2_512, sizeof(hashopctx)); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, signature, 32); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, pubkey, 32); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, message, message_length); + if (r != 0) { + return r; + } + r = sx_hash_digest(&hashopctx, workmem); + if (r != 0) { + return r; + } + + r = sx_ed25519_verify( + (struct sx_ed25519_dgst *)workmem, + (struct sx_ed25519_pt *)pubkey, + (const struct sx_ed25519_v *)(signature + 32), + (const struct sx_ed25519_pt *)signature); + + return r; +} + +int create_ed25519_pubkey(const uint8_t *ed25519, + uint8_t *pubkey) +{ + char workmem[64]; + struct sxhash hashopctx; + int r; + + r = sx_hash_create(&hashopctx, &sxhashalg_sha2_512, sizeof(hashopctx)); + if (r != 0) { + return r; + } + r = sx_hash_feed(&hashopctx, ed25519, 32); + if (r != 0) { + return r; + } + r = sx_hash_digest(&hashopctx, workmem); + if (r != 0) { + return r; + } + /*Wait to make sure hash operation is finished before doing calculations on it + * removing this breaks pubkey generation + */ + r = sx_hash_wait(&hashopctx); + if (r != 0) { + return r; + } + /* The secret scalar s is computed in place from the first half of the + * private key digest. + */ + decode_scalar_25519(workmem); + + /* Clear second half of private key digest: sx_async_ed25519_ptmult_go() + * works on an input of SX_ED25519_DGST_SZ bytes. + */ + safe_memset(workmem+32, 32, 0, 32); + /* Perform point multiplication A = [s]B, to obtain the public key A. */ + r = sx_ed25519_ptmult((const struct sx_ed25519_dgst *)(workmem), + (struct sx_ed25519_pt *)(struct sx_ed25519_pt *)((char *)workmem + 32)); + if (r != 0) { + return r; + } + memcpy(pubkey, workmem+32, 32); + + return r; +} diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c index 90d41501a02b..1f2d2d014a8f 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/key_management.c @@ -10,12 +10,9 @@ #include "cracen_psa.h" #include "platform_keys/platform_keys.h" #include - #include #include #include -#include -#include #include #include #include @@ -30,6 +27,12 @@ #include #include +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else +#include +#include +#endif + extern const uint8_t cracen_N3072[384]; extern nrf_security_mutex_t cracen_mutex_symmetric; @@ -605,8 +608,10 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_ int si_status = 0; psa_algorithm_t key_alg = psa_get_key_algorithm(attributes); const struct sx_pk_ecurve *sx_curve; +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else struct sitask t; - +#endif switch (psa_curve) { case PSA_ECC_FAMILY_BRAINPOOL_P_R1: case PSA_ECC_FAMILY_SECP_R1: @@ -631,9 +636,10 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_ struct si_sig_privkey priv_key; struct si_sig_pubkey pub_key; - +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else char workmem[SX_ED448_DGST_SZ] = {}; - +#endif if (PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)) == PSA_KEY_LOCATION_CRACEN) { if (key_buffer_size != sizeof(ikg_opaque_key)) { @@ -674,6 +680,8 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_ } break; case PSA_ECC_FAMILY_TWISTED_EDWARDS: +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else if (key_bits_attr == 255) { if (key_alg == PSA_ALG_ED25519PH) { priv_key.def = si_sig_def_ed25519ph; @@ -689,12 +697,16 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_ priv_key.key.ed448 = (struct sx_ed448_v *)key_buffer; pub_key.key.ed448 = (struct sx_ed448_pt *)data; } +#endif break; default: return PSA_ERROR_NOT_SUPPORTED; } } - +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 + si_status = create_ed25519_pubkey(key_buffer, data); + *data_length = 32; +#else si_task_init(&t, workmem, sizeof(workmem)); si_sig_create_pubkey(&t, &priv_key, &pub_key); si_task_run(&t); @@ -706,6 +718,7 @@ static psa_status_t export_ecc_public_key_from_keypair(const psa_key_attributes_ } *data_length = expected_pub_key_size; +#endif return PSA_SUCCESS; } diff --git a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c index ca5314e3aa98..8b8d0bf90bde 100644 --- a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c +++ b/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/sign.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include "common.h" #include "cracen_psa.h" - #define SI_IS_MESSAGE (1) #define SI_IS_HASH (0) #define SI_EXTRACT_PUBKEY (1) @@ -40,6 +38,12 @@ #define SI_PSA_IS_KEY_FLAG(flag, attr) ((flag) == (psa_get_key_usage_flags((attr)) & (flag))) #define SI_PSA_IS_KEY_TYPE(flag, attr) ((flag) == (psa_get_key_type((attr)) & (flag))) +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else +#include +#include +#endif + static int cracen_signature_set_hashalgo(const struct sxhashalg **hashalg, psa_algorithm_t alg) { return hash_get_algo(PSA_ALG_SIGN_GET_HASH(alg), hashalg); @@ -120,12 +124,13 @@ static int cracen_signature_prepare_ec_prvkey(struct si_sig_privkey *privkey, ch return SX_ERR_INVALID_ARG; } - if (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS)) { - if (alg == PSA_ALG_PURE_EDDSA) { - privkey->def = si_sig_def_ed25519; - privkey->key.ed25519 = (struct sx_ed25519_v *)key_buffer; - return SX_OK; - } + if (alg == PSA_ALG_PURE_EDDSA) { +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else + privkey->def = si_sig_def_ed25519; + privkey->key.ed25519 = (struct sx_ed25519_v *)key_buffer; +#endif + return SX_OK; } if (IS_ENABLED(PSA_NEED_CRACEN_ED25519PH)) { @@ -211,6 +216,9 @@ static int cracen_signature_prepare_ec_pubkey(struct sitask *t, struct si_sig_pu if (IS_ENABLED(PSA_NEED_CRACEN_PURE_EDDSA_TWISTED_EDWARDS)) { if (alg == PSA_ALG_PURE_EDDSA) { +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 + return SX_OK; +#else pubkey->def = si_sig_def_ed25519; if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(psa_get_key_type(attributes))) { @@ -221,6 +229,7 @@ static int cracen_signature_prepare_ec_pubkey(struct sitask *t, struct si_sig_pu return SX_ERR_INVALID_KEY_SZ; } pubkey->key.ed25519 = (struct sx_ed25519_pt *)pubkey_buffer; +#endif } } @@ -300,6 +309,8 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu { int si_status; const struct sx_pk_ecurve *curve; +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 +#else struct si_sig_privkey privkey = {0}; struct si_sig_signature sign = {0}; struct sitask t; @@ -308,7 +319,7 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; si_task_init(&t, workmem, sizeof(workmem)); - +#endif if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_get_key_type(attributes))) { return silex_statuscodes_to_psa(SX_ERR_INCOMPATIBLE_HW); } @@ -333,7 +344,10 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu if ((int)signature_size < 2 * curve->sz) { return silex_statuscodes_to_psa(SX_ERR_OUTPUT_BUFFER_TOO_SMALL); } - +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 + ed25519_sign(key_buffer, signature, input); + *signature_length = 64; +#else *signature_length = 2 * curve->sz; sign.sz = *signature_length; sign.r = (char *)signature; @@ -370,7 +384,7 @@ static psa_status_t cracen_signature_ecc_sign(int message, const psa_key_attribu si_task_run(&t); si_status = si_task_wait(&t); safe_memzero(workmem, sizeof(workmem)); - +#endif return silex_statuscodes_to_psa(si_status); } @@ -416,6 +430,10 @@ static psa_status_t cracen_signature_ecc_verify(int message, const psa_key_attri if ((int)signature_length != 2 * curve->sz) { return silex_statuscodes_to_psa(SX_ERR_INVALID_SIGNATURE); } + +#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519 + si_status = ed25519_verify(key_buffer, (char *)input, input_length, signature); +#else sign.sz = signature_length; sign.r = (char *)signature; sign.s = (char *)signature + signature_length / 2; @@ -450,7 +468,10 @@ static psa_status_t cracen_signature_ecc_verify(int message, const psa_key_attri } si_task_run(&t); si_status = si_task_wait(&t); + safe_memzero(workmem, sizeof(workmem)); +#endif + return silex_statuscodes_to_psa(si_status); } diff --git a/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig b/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig index 57b478a9ef92..343995dc5bb4 100644 --- a/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig +++ b/subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig @@ -1845,6 +1845,10 @@ config PSA_NEED_CRACEN_KMU_DRIVER default y depends on CRACEN_LIB_KMU +config PSA_NEED_NO_SI_CRYPTO + bool + default y + config PSA_NEED_CRACEN_KMU_ENCRYPTED_KEYS bool default y @@ -1859,5 +1863,12 @@ config PSA_NEED_CRACEN_PLATFORM_KEYS depends on PSA_WANT_AES_KEY_SIZE_256 depends on SOC_NRF54H20_CPUSEC +# CRACEN no sicrypto drivers + +config PSA_NEED_NO_SI_CRYPTO_ED25519 + bool + default y + depends on PSA_WANT_ALG_PURE_EDDSA + depends on PSA_WANT_NO_SI_CRYPTO endmenu