Skip to content

Commit a2e75f4

Browse files
committed
nrf_security: drivers: cracen: Implement ECDSA in cracenpsa
Add support for ECDSA in cracenpsa dirctly using silexpk/sxsymcrypt This bypasses sicrypto, which saves on flash usage Remove sicrypto implementation of ECDSA from being accessible from cracenpsa. Signed-off-by: Dag Erik Gjørvad <dag.erik.gjorvad@nordicsemi.no>
1 parent a39caf0 commit a2e75f4

File tree

14 files changed

+1151
-194
lines changed

14 files changed

+1151
-194
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

+44
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,48 @@ 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(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(char *pubkey, const struct sxhashalg *hashalg, const uint8_t *digest,
389+
size_t digestsz, const struct sx_pk_ecurve *curve,
390+
const uint8_t *signature);
391+
392+
int cracen_ecdsa_sign_message(const struct ecc_priv_key *privkey, size_t privkey_size,
393+
const struct sxhashalg *hashalg, const struct sx_pk_ecurve *curve,
394+
const uint8_t *message, size_t message_length, uint8_t *signature,
395+
size_t signature_size, size_t *signature_length);
396+
397+
int cracen_ecdsa_sign_digest(const struct ecc_priv_key *privkey, size_t privkey_size,
398+
const struct sxhashalg *hashalg, const struct sx_pk_ecurve *curve,
399+
const uint8_t *message, size_t message_length, uint8_t *signature,
400+
size_t signature_size, size_t *signature_length);
401+
402+
int cracen_ecdsa_sign_message_deterministic(const struct ecc_priv_key *privkey, size_t privkey_size,
403+
const struct sxhashalg *hashalg,
404+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
405+
size_t digest_length, uint8_t *signature,
406+
size_t signature_size, size_t *signature_length);
407+
408+
int cracen_ecdsa_sign_digest_deterministic(const struct ecc_priv_key *privkey, size_t privkey_size,
409+
const struct sxhashalg *hashalg,
410+
const struct sx_pk_ecurve *curve, const uint8_t *digest,
411+
size_t digest_length, uint8_t *signature,
412+
size_t signature_size, size_t *signature_length);
413+
414+
int rndinrange_create(const unsigned char *n, size_t nsz, unsigned char *out);
415+
416+
int mac_create_hmac(const struct sxhashalg *hashalg, struct sxhash *hashopctx, const char *key,
417+
size_t keysz, char *workmem, size_t workmemsz);
418+
419+
int hmac_produce(struct sxhash *hashctx, const struct sxhashalg *hashalg, char *out, size_t sz,
420+
char *workmem);
421+
378422
#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+
char *r; /**< Signature element "r". */
380+
char *s; /**< Signature element "s". */
381+
};
382+
struct ecc_priv_key {
383+
const struct sx_pk_ecurve *curve;
384+
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

+68
Original file line numberDiff line numberDiff line change
@@ -853,3 +853,71 @@ psa_status_t cracen_get_opaque_size(const psa_key_attributes_t *attributes, size
853853

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

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(char *const inputs[], 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, size_t input_length, const struct sxhashalg *hashalg,
239+
char *digest);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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_has_finished(pkreq.req);
47+
48+
status = sx_pk_wait(pkreq.req);
49+
if (status != SX_OK) {
50+
return status;
51+
}
52+
outputs = sx_pk_get_output_ops(pkreq.req);
53+
54+
/* When countermeasures are used, the operation may fail with error code
55+
* SX_ERR_NOT_INVERTIBLE. In this case we can try again.
56+
*/
57+
if (status == SX_ERR_NOT_INVERTIBLE) {
58+
sx_pk_release_req(pkreq.req);
59+
if (i == MAX_ECC_ATTEMPTS) {
60+
return SX_ERR_TOO_MANY_ATTEMPTS;
61+
}
62+
} else {
63+
break;
64+
}
65+
}
66+
sx_rdpkmem(pub_key, outputs[0], opsz);
67+
sx_rdpkmem(pub_key + opsz, outputs[1], opsz);
68+
sx_pk_release_req(pkreq.req);
69+
return status;
70+
}
71+
72+
int ecc_create_genprivkey(const struct sx_pk_ecurve *curve, char *priv_key, size_t priv_key_size)
73+
{
74+
int status;
75+
int opsz = sx_pk_curve_opsize(curve);
76+
const char *curve_n = sx_pk_curve_order(curve);
77+
size_t keysz = (size_t)sx_pk_curve_opsize(curve);
78+
79+
if (priv_key_size < keysz) {
80+
return SX_ERR_OUTPUT_BUFFER_TOO_SMALL;
81+
}
82+
83+
/* generate private key, a random number in [1, n-1], where n is the curve
84+
* order
85+
*/
86+
status = rndinrange_create((const unsigned char *)curve_n, opsz, priv_key);
87+
88+
return status;
89+
}

0 commit comments

Comments
 (0)