Skip to content

Commit dd4c71f

Browse files
committed
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 Remove sicrypto implementation of ECDSA being accessible from cracenpsa. Signed-off-by: Dag Erik Gjørvad <dag.erik.gjorvad@nordicsemi.no>
1 parent ef72347 commit dd4c71f

File tree

16 files changed

+1232
-228
lines changed

16 files changed

+1232
-228
lines changed

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

+8
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

+40
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,44 @@ int cracen_ed25519ph_verify(const uint8_t *pub_key, const char *message, size_t
375375

376376
int cracen_ed25519_create_pubkey(const uint8_t *priv_key, uint8_t *pub_key);
377377

378+
int be_cmp(const unsigned char *a, const unsigned char *b, size_t sz, int carry);
379+
380+
int ecc_create_genpubkey(const char *priv_key, char *pub_key, const struct sx_pk_ecurve *curve);
381+
382+
int ecc_create_genprivkey(const struct sx_pk_ecurve *curve, char *priv_key, size_t priv_key_size);
383+
384+
int cracen_ecdsa_verify_message(const char *pubkey, const struct sxhashalg *hashalg,
385+
const uint8_t *message, size_t message_length,
386+
const struct sx_pk_ecurve *curve, const uint8_t *signature);
387+
388+
int cracen_ecdsa_verify_digest(const char *pubkey, const uint8_t *digest, size_t digestsz,
389+
const struct sx_pk_ecurve *curve, const uint8_t *signature);
390+
391+
int cracen_ecdsa_sign_message(const struct ecc_priv_key *privkey, const struct sxhashalg *hashalg,
392+
const struct sx_pk_ecurve *curve, const uint8_t *message,
393+
size_t message_length, const uint8_t *signature);
394+
395+
int cracen_ecdsa_sign_digest(const struct ecc_priv_key *privkey, const struct sxhashalg *hashalg,
396+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
397+
size_t digest_length, const uint8_t *signature);
398+
399+
int cracen_ecdsa_sign_message_deterministic(const struct ecc_priv_key *privkey,
400+
const struct sxhashalg *hashalg,
401+
const struct sx_pk_ecurve *curve,
402+
const uint8_t *message, size_t message_length,
403+
const uint8_t *signature);
404+
405+
int cracen_ecdsa_sign_digest_deterministic(const struct ecc_priv_key *privkey,
406+
const struct sxhashalg *hashalg,
407+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
408+
size_t digestsz, const uint8_t *signature);
409+
410+
int rndinrange_create(const unsigned char *n, size_t nsz, unsigned char *out);
411+
412+
int mac_create_hmac(const struct sxhashalg *hashalg, struct sxhash *hashopctx, const char *key,
413+
size_t keysz, char *workmem, size_t workmemsz);
414+
415+
int hmac_produce(struct sxhash *hashctx, const struct sxhashalg *hashalg, char *out, size_t sz,
416+
char *workmem);
417+
378418
#endif /* CRACEN_PSA_H */

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

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

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

+67
Original file line numberDiff line numberDiff line change
@@ -852,3 +852,70 @@ 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(const char *inputs[], const size_t inputs_lengths[], size_t input_count,
891+
const struct sxhashalg *hashalg, char *digest)
892+
{
893+
int status;
894+
struct sxhash hashopctx;
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_input(const char *input, const size_t input_length, const struct sxhashalg *hashalg,
918+
char *digest)
919+
{
920+
return hash_all_inputs(&input, &input_length, 1, hashalg, digest);
921+
}

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

+51
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,54 @@ 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 Big-Endian addition.
192+
*
193+
* @param v Big-endian Value
194+
* @param v_size size of v
195+
* @param summand Summand.
196+
*
197+
*/
198+
void be_add(unsigned char *v, size_t v_size, size_t summand);
199+
200+
/**
201+
* @brief Big-Endian compare with carry.
202+
*
203+
* @param a First value to be compared
204+
* @param b Second value to be compared
205+
* @param size Size of a and b.
206+
* @param carry Value of the carry.
207+
*
208+
* \retval 0 if equal.
209+
* \retval 1 if a > b.
210+
* \retval -1 if a < b.
211+
*/
212+
int be_cmp(const unsigned char *a, const unsigned char *b, size_t sz, int carry);
213+
214+
/**
215+
* @brief Hash several elements at different locations in memory
216+
*
217+
* @param inputs[in] Array of pointers to elements that will be hashed.
218+
* @param inputs_lengths[in] Array of lengths of elements to be hashed.
219+
* @param input_count[in] Number of elements to be hashed.
220+
* @param hashalg[in] Hash algorithm to be used in sxhashalg format.
221+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
222+
*
223+
* @return sxsymcrypt error code.
224+
*/
225+
int hash_all_inputs(const char *inputs[], const size_t inputs_lengths[], size_t input_count,
226+
const struct sxhashalg *hashalg, char *digest);
227+
228+
/**
229+
* @brief Hash a single element
230+
*
231+
* @param inputs[in] Pointer to elements that will be hashed.
232+
* @param inputs_lengths[in] Length of element to be hashed.
233+
* @param hashalg[in] hash algorithm to be used in sxhashalg format.
234+
* @param digest[out] Buffer of at least sx_hash_get_alg_digestsz(hashalg) bytes.
235+
*
236+
* @return sxsymcrypt error code.
237+
*/
238+
int hash_input(const char *input, const size_t input_length, const struct sxhashalg *hashalg,
239+
char *digest);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* ECC key pair generation.
2+
* Based on FIPS 186-4, section B.4.2 "Key Pair Generation by Testing
3+
* Candidates".
4+
*
5+
* Copyright (c) 2023 Nordic Semiconductor ASA
6+
*
7+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
8+
*/
9+
10+
#include <string.h>
11+
#include <silexpk/core.h>
12+
#include <silexpk/iomem.h>
13+
#include <silexpk/cmddefs/ecc.h>
14+
#include <cracen/statuscodes.h>
15+
#include "cracen_psa.h"
16+
17+
#define MAX_ECC_ATTEMPTS 10
18+
19+
int ecc_create_genpubkey(const char *priv_key, char *pub_key, const struct sx_pk_ecurve *curve)
20+
{
21+
const char **outputs;
22+
struct sx_pk_acq_req pkreq;
23+
struct sx_pk_inops_ecp_mult inputs;
24+
int opsz;
25+
int status;
26+
27+
for (int i = 0; i <= MAX_ECC_ATTEMPTS; i++) {
28+
pkreq = sx_pk_acquire_req(SX_PK_CMD_ECC_PTMUL);
29+
if (pkreq.status) {
30+
return pkreq.status;
31+
}
32+
pkreq.status = sx_pk_list_ecc_inslots(pkreq.req, curve, 0,
33+
(struct sx_pk_slot *)&inputs);
34+
if (pkreq.status) {
35+
return pkreq.status;
36+
}
37+
38+
opsz = sx_pk_curve_opsize(curve);
39+
40+
/* Write the private key (random) into ba414ep device memory */
41+
sx_wrpkmem(inputs.k.addr, priv_key, opsz);
42+
sx_pk_write_curve_gen(pkreq.req, curve, inputs.px, inputs.py);
43+
44+
sx_pk_run(pkreq.req);
45+
46+
status = sx_pk_wait(pkreq.req);
47+
if (status != SX_OK) {
48+
return status;
49+
}
50+
outputs = sx_pk_get_output_ops(pkreq.req);
51+
52+
/* When countermeasures are used, the operation may fail with error code
53+
* SX_ERR_NOT_INVERTIBLE. In this case we can try again.
54+
*/
55+
if (status == SX_ERR_NOT_INVERTIBLE) {
56+
sx_pk_release_req(pkreq.req);
57+
if (i == MAX_ECC_ATTEMPTS) {
58+
return SX_ERR_TOO_MANY_ATTEMPTS;
59+
}
60+
} else {
61+
break;
62+
}
63+
}
64+
sx_rdpkmem(pub_key, outputs[0], opsz);
65+
sx_rdpkmem(pub_key + opsz, outputs[1], opsz);
66+
sx_pk_release_req(pkreq.req);
67+
return status;
68+
}
69+
70+
int ecc_create_genprivkey(const struct sx_pk_ecurve *curve, char *priv_key, size_t priv_key_size)
71+
{
72+
int status;
73+
int opsz = sx_pk_curve_opsize(curve);
74+
const char *curve_n = sx_pk_curve_order(curve);
75+
size_t keysz = (size_t)sx_pk_curve_opsize(curve);
76+
77+
if (priv_key_size < keysz) {
78+
return SX_ERR_OUTPUT_BUFFER_TOO_SMALL;
79+
}
80+
81+
/* generate private key, a random number in [1, n-1], where n is the curve
82+
* order
83+
*/
84+
status = rndinrange_create((const unsigned char *)curve_n, opsz, priv_key);
85+
86+
return status;
87+
}

0 commit comments

Comments
 (0)