Skip to content

Commit 0bd5d24

Browse files
degjorvaendre-nordic
authored andcommitted
nrf_security: drivers: cracen: Implement ECDSA in cracenpsa
Add support for ECDSA in cracenpsa Directly using silexpk/sxsymcrypt This bypasses sicrypto, which saves on flash usage Adding support for hmac without sicrypto. Remove sicrypto implementation of ECDSA being accessible from cracenpsa. Various refactors to support this Signed-off-by: Dag Erik Gjørvad <[email protected]>
1 parent 4177fe2 commit 0bd5d24

File tree

20 files changed

+1476
-270
lines changed

20 files changed

+1476
-270
lines changed

subsys/nrf_security/src/core/lite/psa_core_lite.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <psa_crypto_driver_wrappers.h>
1010
#include <cracen_psa_kmu.h>
1111
#include <cracen/mem_helpers.h>
12+
#include <cracen_psa_eddsa.h>
1213

1314
#if defined(CONFIG_PSA_CORE_LITE_NSIB_ED25519_OPTIMIZATIONS)
1415
#include "cracen_psa.h"

subsys/nrf_security/src/drivers/cracen/cracenpsa/cracenpsa.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ list(APPEND cracen_driver_sources
1515
${CMAKE_CURRENT_LIST_DIR}/src/common.c
1616
${CMAKE_CURRENT_LIST_DIR}/src/mem_helpers.c
1717
${CMAKE_CURRENT_LIST_DIR}/src/ec_helpers.c
18+
${CMAKE_CURRENT_LIST_DIR}/src/ecc.c
19+
${CMAKE_CURRENT_LIST_DIR}/src/rndinrange.c
1820

1921
# Note: We always need to have blkcipher.c and ctr_drbg.c since it
2022
# is used directly by many Cracen drivers.
@@ -44,7 +46,10 @@ endif()
4446
if(CONFIG_PSA_NEED_CRACEN_ASYMMETRIC_SIGNATURE_DRIVER)
4547
list(APPEND cracen_driver_sources
4648
${CMAKE_CURRENT_LIST_DIR}/src/sign.c
49+
${CMAKE_CURRENT_LIST_DIR}/src/ecdsa.c
50+
${CMAKE_CURRENT_LIST_DIR}/src/ecc.c
4751
${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c
52+
${CMAKE_CURRENT_LIST_DIR}/src/hmac.c
4853
)
4954
endif()
5055

@@ -62,8 +67,11 @@ endif()
6267

6368
if(CONFIG_PSA_NEED_CRACEN_KEY_MANAGEMENT_DRIVER OR CONFIG_PSA_NEED_CRACEN_KMU_DRIVER OR CONFIG_MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
6469
list(APPEND cracen_driver_sources
70+
${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c
6571
${CMAKE_CURRENT_LIST_DIR}/src/key_management.c
6672
${CMAKE_CURRENT_LIST_DIR}/src/ed25519.c
73+
${CMAKE_CURRENT_LIST_DIR}/src/ecdsa.c
74+
${CMAKE_CURRENT_LIST_DIR}/src/ecc.c
6775
)
6876
endif()
6977

subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,4 @@ psa_status_t cracen_spake2p_get_shared_key(cracen_spake2p_operation_t *operation
361361

362362
psa_status_t cracen_spake2p_abort(cracen_spake2p_operation_t *operation);
363363

364-
int cracen_ed25519_sign(const uint8_t *priv_key, char *signature, const uint8_t *message,
365-
size_t message_length);
366-
367-
int cracen_ed25519_verify(const uint8_t *pub_key, const char *message, size_t message_length,
368-
const char *signature);
369-
370-
int cracen_ed25519ph_sign(const uint8_t *priv_key, char *signature, const uint8_t *message,
371-
size_t message_length, bool is_message);
372-
373-
int cracen_ed25519ph_verify(const uint8_t *pub_key, const char *message, size_t message_length,
374-
const char *signature, bool is_message);
375-
376-
int cracen_ed25519_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key);
377-
378364
#endif /* CRACEN_PSA_H */
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef CRACEN_PSA_ECDSA_H
8+
#define CRACEN_PSA_ECDSA_H
9+
10+
#include <psa/crypto.h>
11+
12+
int cracen_ecdsa_verify_message(const char *pubkey, const struct sxhashalg *hashalg,
13+
const uint8_t *message, size_t message_length,
14+
const struct sx_pk_ecurve *curve, const uint8_t *signature);
15+
16+
int cracen_ecdsa_verify_digest(const char *pubkey, const uint8_t *digest, size_t digestsz,
17+
const struct sx_pk_ecurve *curve, const uint8_t *signature);
18+
19+
int cracen_ecdsa_sign_message(const struct ecc_priv_key *privkey, const struct sxhashalg *hashalg,
20+
const struct sx_pk_ecurve *curve, const uint8_t *message,
21+
size_t message_length, uint8_t *signature);
22+
23+
int cracen_ecdsa_sign_digest(const struct ecc_priv_key *privkey, const struct sxhashalg *hashalg,
24+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
25+
size_t digest_length, uint8_t *signature);
26+
27+
int cracen_ecdsa_sign_message_deterministic(const struct ecc_priv_key *privkey,
28+
const struct sxhashalg *hashalg,
29+
const struct sx_pk_ecurve *curve,
30+
const uint8_t *message, size_t message_length,
31+
uint8_t *signature);
32+
33+
int cracen_ecdsa_sign_digest_deterministic(const struct ecc_priv_key *privkey,
34+
const struct sxhashalg *hashalg,
35+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
36+
size_t digestsz, uint8_t *signature);
37+
38+
#endif /* CRACEN_PSA_ECDSA_H */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <psa/crypto.h>
8+
9+
int cracen_ed25519_sign(const uint8_t *priv_key, char *signature, const uint8_t *message,
10+
size_t message_length);
11+
12+
int cracen_ed25519_verify(const uint8_t *pub_key, const char *message, size_t message_length,
13+
const char *signature);
14+
15+
int cracen_ed25519ph_sign(const uint8_t *priv_key, char *signature, const uint8_t *message,
16+
size_t message_length, bool is_message);
17+
18+
int cracen_ed25519ph_verify(const uint8_t *pub_key, const char *message, size_t message_length,
19+
const char *signature, bool is_message);
20+
21+
int cracen_ed25519_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key);

subsys/nrf_security/src/drivers/cracen/cracenpsa/include/cracen_psa_primitives.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,26 @@ struct cracen_pake_operation {
371371
};
372372
};
373373
typedef struct cracen_pake_operation cracen_pake_operation_t;
374+
375+
struct ecdsa_signature {
376+
size_t sz; /** Total signature size, in bytes. */
377+
char *r; /** Signature element "r". */
378+
char *s; /** Signature element "s". */
379+
};
380+
381+
struct ecc_priv_key {
382+
const struct sx_pk_ecurve *curve;
383+
const char *d; /** Private key value d */
384+
};
385+
386+
struct ecc_pub_key {
387+
const struct sx_pk_ecurve *curve;
388+
char *qx; /** x coordinate of a point on the curve */
389+
char *qy; /** y coordinate of a point on the curve */
390+
};
391+
392+
struct ecc_keypair {
393+
struct ecc_priv_key priv_key;
394+
struct ecc_pub_key pub_key;
395+
};
374396
#endif /* CRACEN_PSA_PRIMITIVES_H */

subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,3 +852,85 @@ psa_status_t cracen_get_opaque_size(const psa_key_attributes_t *attributes, size
852852

853853
return PSA_ERROR_INVALID_ARGUMENT;
854854
}
855+
856+
void be_add(unsigned char *v, size_t sz, size_t summand)
857+
{
858+
while (sz > 0) {
859+
sz--;
860+
summand += v[sz];
861+
v[sz] = summand & 0xFF;
862+
summand >>= 8;
863+
}
864+
}
865+
866+
int be_cmp(const unsigned char *a, const unsigned char *b, size_t sz, int carry)
867+
{
868+
unsigned int neq = 0;
869+
unsigned int gt = 0;
870+
unsigned int ucarry;
871+
unsigned int d;
872+
unsigned int lt;
873+
874+
/* transform carry to work with unsigned numbers */
875+
ucarry = 0x100 + carry;
876+
877+
for (int i = sz - 1; i >= 0; i--) {
878+
d = ucarry + a[i] - b[i];
879+
ucarry = 0xFF + (d >> 8);
880+
neq |= d & 0xFF;
881+
}
882+
883+
neq |= ucarry & 0xFF;
884+
lt = ucarry < 0x100;
885+
gt = neq && !lt;
886+
887+
return (gt ? 1 : 0) - (lt ? 1 : 0);
888+
}
889+
890+
int hash_all_inputs_with_context(struct sxhash *hashopctx, const char *inputs[],
891+
const size_t inputs_lengths[], size_t input_count,
892+
const struct sxhashalg *hashalg, char *digest)
893+
{
894+
int status;
895+
896+
status = sx_hash_create(hashopctx, hashalg, sizeof(*hashopctx));
897+
if (status != SX_OK) {
898+
return status;
899+
}
900+
901+
for (size_t i = 0; i < input_count; i++) {
902+
status = sx_hash_feed(hashopctx, inputs[i], inputs_lengths[i]);
903+
if (status != SX_OK) {
904+
return status;
905+
}
906+
}
907+
status = sx_hash_digest(hashopctx, digest);
908+
if (status != SX_OK) {
909+
return status;
910+
}
911+
912+
status = sx_hash_wait(hashopctx);
913+
914+
return status;
915+
}
916+
917+
int hash_all_inputs(const char *inputs[], const size_t inputs_lengths[], size_t input_count,
918+
const struct sxhashalg *hashalg, char *digest)
919+
{
920+
struct sxhash hashopctx;
921+
922+
return hash_all_inputs_with_context(&hashopctx, inputs, inputs_lengths, input_count,
923+
hashalg, digest);
924+
}
925+
926+
int hash_input(const char *input, const size_t input_length, const struct sxhashalg *hashalg,
927+
char *digest)
928+
{
929+
return hash_all_inputs(&input, &input_length, 1, hashalg, digest);
930+
}
931+
932+
int hash_input_with_context(struct sxhash *hashopctx, const char *input, const size_t input_length,
933+
const struct sxhashalg *hashalg, char *digest)
934+
{
935+
return hash_all_inputs_with_context(hashopctx, &input, &input_length, 1, hashalg, digest);
936+
}

subsys/nrf_security/src/drivers/cracen/cracenpsa/src/common.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,106 @@ psa_status_t cracen_cipher_crypt_ecb(const struct sxkeyref *key, const uint8_t *
186186
* @return sxsymcrypt error code.
187187
*/
188188
int cracen_prepare_ik_key(const uint8_t *user_data);
189+
190+
/**
191+
* @brief Compute v = v + summand.
192+
* \note v is an unsigned integer stored as a big endian byte array of sz bytes.
193+
* Summand must be less than or equal to the maximum value of a size_t minus 255.
194+
* The final carry is discarded: addition is modulo 2^(sz*8).
195+
*
196+
* @param v Big-endian Value
197+
* @param v_size size of v
198+
* @param summand Summand.
199+
*
200+
*/
201+
void be_add(unsigned char *v, size_t v_size, size_t summand);
202+
203+
/**
204+
* @brief Big-Endian compare with carry.
205+
* \note
206+
*
207+
* @param a First value to be compared
208+
* @param b Second value to be compared
209+
* @param size Size of a and b.
210+
* @param carry Value of the carry.
211+
*
212+
* \retval 0 if equal.
213+
* \retval 1 if a > b.
214+
* \retval -1 if a < b.
215+
*/
216+
int be_cmp(const unsigned char *a, const unsigned char *b, size_t sz, int carry);
217+
218+
/**
219+
* @brief Hash several elements at different locations in memory
220+
*
221+
* @param inputs[in] Array of pointers to elements that will be hashed.
222+
* @param inputs_lengths[in] Array of lengths of elements to be hashed.
223+
* @param input_count[in] Number of elements to be hashed.
224+
* @param hashalg[in] Hash algorithm to be used in sxhashalg format.
225+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
226+
*
227+
* @return sxsymcrypt status code.
228+
*/
229+
int hash_all_inputs(const char *inputs[], const size_t inputs_lengths[], size_t input_count,
230+
const struct sxhashalg *hashalg, char *digest);
231+
232+
/**
233+
* @brief Hash several elements at different locations in memory with a previously created hash
234+
* context(sxhash)
235+
*
236+
* @param sxhashopctx[in] Pointer to the sxhash context.
237+
* @param inputs[in] Array of pointers to elements that will be hashed.
238+
* @param inputs_lengths[in] Array of lengths of elements to be hashed.
239+
* @param input_count[in] Number of elements to be hashed.
240+
* @param hashalg[in] Hash algorithm to be used in sxhashalg format.
241+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
242+
*
243+
* @return sxsymcrypt status code.
244+
*/
245+
int hash_all_inputs_with_context(struct sxhash *sxhashopctx, const char *inputs[],
246+
const size_t inputs_lengths[], size_t input_count,
247+
const struct sxhashalg *hashalg, char *digest);
248+
249+
/**
250+
* @brief Hash a single element
251+
*
252+
* @param inputs[in] Pointer to the element that will be hashed.
253+
* @param input_length[in] Length of the element to be hashed.
254+
* @param hashalg[in] Hash algorithm to be used in sxhashalg format.
255+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
256+
*
257+
* @return sxsymcrypt status code.
258+
*/
259+
int hash_input(const char *input, const size_t input_length, const struct sxhashalg *hashalg,
260+
char *digest);
261+
262+
/**
263+
* @brief Hash a single element with a previously created hash context(sxhash)
264+
*
265+
* @param sxhashopctx[in] Pointer to the sxhash context.
266+
* @param input[in] Pointer to element that will be hashed.
267+
* @param input_length[in] Length of element to be hashed.
268+
* @param hashalg[in] hash algorithm to be used in sxhashalg format.
269+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
270+
*
271+
* @return sxsymcrypt status code.
272+
*/
273+
int hash_input_with_context(struct sxhash *hashopctx, const char *input, const size_t input_length,
274+
const struct sxhashalg *hashalg, char *digest);
275+
276+
/**
277+
* @brief Generate a random number within the specified range.
278+
*
279+
* \note This function generates a random number strictly less than the given upper limit (`n`).
280+
* The generated random number is evenly distributed over the range [0, n-1]. If the range
281+
* is invalid (e.g., `n` is zero, less than three, or even), an error code is returned.
282+
*
283+
* @param n[in] Pointer to a buffer holding the upper limit of the random range.
284+
* The upper limit must be a non-zero odd number.
285+
* @param nsz[in] Size of the upper limit buffer in bytes.
286+
* @param out[out] Buffer to store the generated random number.
287+
* The size of `out` should be at least `nsz`.
288+
*
289+
* @return sxsymcrypt status code:
290+
*/
291+
int rndinrange_create(const unsigned char *n, size_t nsz, unsigned char *out);

0 commit comments

Comments
 (0)