Skip to content

Commit

Permalink
nrf_security: drivers: cracen: Adding support for ed25519 without sic…
Browse files Browse the repository at this point in the history
…rypto

Adding support directly using silexpk/sxsymcrypt files for ed25519
This bypasses sicrypto, which saves on flash usage
Primarily intended for bootloader usecase

Signed-off-by: Dag Erik Gjørvad <[email protected]>
  • Loading branch information
degjorva committed Jan 8, 2025
1 parent 6e0cb3a commit 16a31d6
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 18 deletions.
7 changes: 7 additions & 0 deletions subsys/nrf_security/Kconfig.psa.nordic
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
211 changes: 211 additions & 0 deletions subsys/nrf_security/src/drivers/cracen/cracenpsa/src/ed25519.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <string.h>
#include <sxsymcrypt/sha2.h>
#include <silexpk/ed25519.h>
#include <cracen/ec_helpers.h>
#include <sxsymcrypt/hash.h>
#include <cracen/mem_helpers.h>

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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@
#include "cracen_psa.h"
#include "platform_keys/platform_keys.h"
#include <nrf_security_mutexes.h>

#include <sicrypto/drbghash.h>
#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 All @@ -30,6 +27,12 @@
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/byteorder.h>

#if CONFIG_PSA_NEED_NO_SI_CRYPTO_ED25519
#else
#include <sicrypto/ed25519.h>
#include <sicrypto/ed25519ph.h>
#endif

extern const uint8_t cracen_N3072[384];

extern nrf_security_mutex_t cracen_mutex_symmetric;
Expand Down Expand Up @@ -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:
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down
Loading

0 comments on commit 16a31d6

Please sign in to comment.