Skip to content

Commit f3e720e

Browse files
degjorvanordicjm
authored andcommitted
nrf_security: CRACEN: Update to use PK_SET_COMMAND function
Update the following functionality to use PK_SET_COMMAND instead of aquiring and releasing each use of CRACEN. ECDSA, ED25519, ED448, IKG and the RSA keygen This to eliminate a possible race condition and possibly save power. Signed-off-by: Dag Erik Gjørvad <[email protected]>
1 parent 3fabb5d commit f3e720e

File tree

13 files changed

+525
-610
lines changed

13 files changed

+525
-610
lines changed

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

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -40,77 +40,47 @@
4040
#include "coprime_check.h"
4141

4242
/* Perform modular inversion of a, using b as the modulo. */
43-
static int modular_inversion_start(struct cracen_coprimecheck *coprimecheck)
43+
static int modular_inversion_run(sx_pk_req *req, struct cracen_coprimecheck *coprimecheck)
4444
{
45-
int sx_status;
46-
struct sx_pk_acq_req pkreq;
4745
struct sx_pk_inops_mod_single_op_cmd inputs;
4846
size_t bsz = coprimecheck->bsz;
4947
size_t asz = coprimecheck->asz;
5048
int sizes[] = {bsz, asz};
5149

5250
/* b is odd, we can use command SX_PK_CMD_ODD_MOD_INV */
53-
pkreq = sx_pk_acquire_req(SX_PK_CMD_ODD_MOD_INV);
54-
if (pkreq.status) {
55-
return pkreq.status;
56-
}
51+
sx_pk_set_cmd(req, SX_PK_CMD_ODD_MOD_INV);
5752

58-
pkreq.status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs);
59-
if (pkreq.status) {
60-
return pkreq.status;
53+
int status = sx_pk_list_gfp_inslots(req, sizes, (struct sx_pk_slot *)&inputs);
54+
55+
if (status != SX_OK) {
56+
return status;
6157
}
6258

6359
sx_wrpkmem(inputs.n.addr, coprimecheck->b, bsz);
6460
sx_wrpkmem(inputs.b.addr, coprimecheck->a, asz);
6561

66-
sx_pk_run(pkreq.req);
62+
sx_pk_run(req);
6763

68-
sx_status = sx_pk_wait(pkreq.req);
69-
return sx_status;
70-
}
71-
72-
static int modular_reduction_finish(uint8_t *workmem, struct sx_pk_acq_req *pkreq,
73-
struct cracen_coprimecheck *coprimecheck)
74-
{
75-
const uint8_t **outputs = sx_pk_get_output_ops(pkreq->req);
76-
int opsz = sx_pk_get_opsize(pkreq->req);
77-
size_t bsz = coprimecheck->bsz;
78-
79-
/* copy to workmem the result of the modular reduction, to be found
80-
* at the end of the device memory slots
81-
*/
82-
sx_rdpkmem(workmem, outputs[0] + opsz - bsz, bsz);
83-
84-
sx_pk_release_req(pkreq->req);
85-
86-
/* update the task's parameters related to a */
87-
coprimecheck->a = workmem;
88-
coprimecheck->asz = bsz;
89-
90-
return modular_inversion_start(coprimecheck);
64+
return sx_pk_wait(req);
9165
}
9266

9367
/* Perform modular reduction of a, using b as the modulo. */
94-
static int modular_reduction_start(uint8_t *workmem, struct cracen_coprimecheck *coprimecheck)
68+
static int modular_reduction_run(sx_pk_req *req, uint8_t *workmem,
69+
struct cracen_coprimecheck *coprimecheck)
9570
{
96-
int sx_status;
97-
struct sx_pk_acq_req pkreq;
9871
struct sx_pk_inops_mod_single_op_cmd inputs;
9972
size_t bsz = coprimecheck->bsz;
10073
size_t asz = coprimecheck->asz;
10174

102-
/* b is odd, we can use command SX_PK_CMD_ODD_MOD_REDUCE */
103-
pkreq = sx_pk_acquire_req(SX_PK_CMD_ODD_MOD_REDUCE);
104-
if (pkreq.status) {
105-
return pkreq.status;
106-
}
75+
sx_pk_set_cmd(req, SX_PK_CMD_ODD_MOD_REDUCE);
10776

10877
/* give the largest size for both inputs, in this case it is asz */
10978
int sizes[] = {asz, asz};
11079

111-
sx_status = sx_pk_list_gfp_inslots(pkreq.req, sizes, (struct sx_pk_slot *)&inputs);
112-
if (sx_status) {
113-
return sx_status;
80+
int status = sx_pk_list_gfp_inslots(req, sizes, (struct sx_pk_slot *)&inputs);
81+
82+
if (status != SX_OK) {
83+
return status;
11484
}
11585

11686
/* Copy modulo and operand to the device memory slots. Note that the
@@ -120,19 +90,32 @@ static int modular_reduction_start(uint8_t *workmem, struct cracen_coprimecheck
12090
sx_wrpkmem(inputs.n.addr + asz - bsz, coprimecheck->b, bsz);
12191
sx_wrpkmem(inputs.b.addr, coprimecheck->a, asz);
12292

123-
sx_pk_run(pkreq.req);
124-
sx_status = sx_pk_wait(pkreq.req);
125-
if (sx_status != SX_OK) {
126-
sx_pk_release_req(pkreq.req);
127-
return sx_status;
93+
sx_pk_run(req);
94+
status = sx_pk_wait(req);
95+
if (status != SX_OK) {
96+
return status;
12897
}
129-
return modular_reduction_finish(workmem, &pkreq, coprimecheck);
98+
99+
/* Read the result of the modular reduction */
100+
const uint8_t **outputs = sx_pk_get_output_ops(req);
101+
int opsz = sx_pk_get_opsize(req);
102+
103+
/* copy to workmem the result of the modular reduction, to be found
104+
* at the end of the device memory slots
105+
*/
106+
sx_rdpkmem(workmem, outputs[0] + opsz - bsz, bsz);
107+
108+
/* update the task's parameters related to a */
109+
coprimecheck->a = workmem;
110+
coprimecheck->asz = bsz;
111+
112+
return SX_OK;
130113
}
131114

132-
int cracen_coprime_check(uint8_t *workmem, size_t workmemsz, const uint8_t *a, size_t asz,
133-
const uint8_t *b, size_t bsz)
115+
int coprime_check_run(sx_pk_req *req, uint8_t *workmem, size_t workmemsz, const uint8_t *a,
116+
size_t asz, const uint8_t *b, size_t bsz)
134117
{
135-
int sx_status;
118+
int status;
136119
int a_is_odd;
137120
int b_is_odd;
138121
size_t minworkmemsz;
@@ -184,9 +167,31 @@ int cracen_coprime_check(uint8_t *workmem, size_t workmemsz, const uint8_t *a, s
184167
coprimecheck.bsz = bsz;
185168

186169
if (asz > bsz) {
187-
sx_status = modular_reduction_start(workmem, &coprimecheck);
188-
} else {
189-
sx_status = modular_inversion_start(&coprimecheck);
170+
/* First do modular reduction, then inversion */
171+
status = modular_reduction_run(req, workmem, &coprimecheck);
172+
if (status != SX_OK) {
173+
return status;
174+
}
190175
}
191-
return sx_status;
176+
177+
return modular_inversion_run(req, &coprimecheck);
178+
}
179+
180+
int cracen_coprime_check(uint8_t *workmem, size_t workmemsz, const uint8_t *a, size_t asz,
181+
const uint8_t *b, size_t bsz)
182+
{
183+
struct sx_pk_acq_req pkreq;
184+
int status;
185+
186+
pkreq = sx_pk_acquire_req(SX_PK_CMD_ODD_MOD_INV);
187+
if (pkreq.status) {
188+
sx_pk_release_req(pkreq.req);
189+
return pkreq.status;
190+
}
191+
192+
status = coprime_check_run(pkreq.req, workmem, workmemsz, a, asz, b, bsz);
193+
194+
sx_pk_release_req(pkreq.req);
195+
196+
return status;
192197
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define COPRIME_CHECK_HEADER_FILE
99

1010
#include <stdint.h>
11+
#include <silexpk/core.h>
1112

1213
/** Function to check if two integer numbers are coprime.
1314
* @param[in] a Unsigned integer stored as a big endian byte array.
@@ -31,4 +32,10 @@
3132
int cracen_coprime_check(uint8_t *workmem, size_t workmemsz, const uint8_t *a, size_t asz,
3233
const uint8_t *b, size_t bsz);
3334

35+
/** Same as cracen_coprime_check, but uses an already-acquired request.
36+
* This allows chaining multiple CRACEN operations without releasing between them.
37+
*/
38+
int coprime_check_run(sx_pk_req *req, uint8_t *workmem, size_t workmemsz, const uint8_t *a,
39+
size_t asz, const uint8_t *b, size_t bsz);
40+
3441
#endif

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,27 @@ int ecc_genpubkey(const uint8_t *priv_key, uint8_t *pub_key, const struct sx_pk_
2525
struct sx_pk_acq_req pkreq;
2626
struct sx_pk_inops_ecp_mult inputs;
2727
int opsz;
28-
int status = SX_ERR_NOT_INVERTIBLE;
28+
int status = SX_ERR_CORRUPTION_DETECTED;
2929
int attempts = 0;
3030

3131
opsz = sx_pk_curve_opsize(curve);
3232

33-
while (status == SX_ERR_NOT_INVERTIBLE) {
34-
pkreq = sx_pk_acquire_req(SX_PK_CMD_ECC_PTMUL);
35-
if (pkreq.status) {
36-
return pkreq.status;
33+
/* Acquire CRACEN once for all retry attempts */
34+
pkreq = sx_pk_acquire_req(SX_PK_CMD_ECC_PTMUL);
35+
if (pkreq.status) {
36+
sx_pk_release_req(pkreq.req);
37+
return pkreq.status;
38+
}
39+
40+
do {
41+
if (attempts > 0) {
42+
sx_pk_set_cmd(pkreq.req, SX_PK_CMD_ECC_PTMUL);
3743
}
44+
3845
pkreq.status =
3946
sx_pk_list_ecc_inslots(pkreq.req, curve, 0, (struct sx_pk_slot *)&inputs);
4047
if (pkreq.status) {
48+
sx_pk_release_req(pkreq.req);
4149
return pkreq.status;
4250
}
4351

@@ -48,22 +56,20 @@ int ecc_genpubkey(const uint8_t *priv_key, uint8_t *pub_key, const struct sx_pk_
4856
sx_pk_run(pkreq.req);
4957

5058
status = sx_pk_wait(pkreq.req);
51-
if (status != SX_OK) {
52-
return status;
53-
}
54-
outputs = (const uint8_t **)sx_pk_get_output_ops(pkreq.req);
5559

5660
/* When countermeasures are used, the operation may fail with error code
5761
* SX_ERR_NOT_INVERTIBLE. In this case we can try again.
5862
*/
5963
if (status == SX_ERR_NOT_INVERTIBLE) {
60-
sx_pk_release_req(pkreq.req);
6164
if (++attempts == MAX_ECC_ATTEMPTS) {
62-
status = SX_ERR_TOO_MANY_ATTEMPTS;
65+
sx_pk_release_req(pkreq.req);
66+
return SX_ERR_TOO_MANY_ATTEMPTS;
6367
}
6468
}
65-
}
69+
} while (status == SX_ERR_NOT_INVERTIBLE);
70+
6671
if (status == SX_OK) {
72+
outputs = (const uint8_t **)sx_pk_get_output_ops(pkreq.req);
6773
sx_rdpkmem(pub_key, outputs[0], opsz);
6874
sx_rdpkmem(pub_key + opsz, outputs[1], opsz);
6975
}

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

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -170,26 +170,22 @@ static void ecdsa_read_sig(struct cracen_signature *sig, const uint8_t *r, const
170170
sx_rdpkmem(sig->s, s, opsz);
171171
}
172172

173-
static int ecdsa_run_generate_sign(struct sx_pk_acq_req *pkreq,
174-
const struct cracen_ecc_priv_key *privkey,
175-
const struct sx_pk_ecurve *curve, const uint8_t *workmem,
176-
size_t digestsz, size_t opsz,
177-
struct sx_pk_inops_ecdsa_generate *inputs)
173+
static int ecdsa_run_generate_sign(sx_pk_req *req,
174+
const struct cracen_ecc_priv_key *privkey,
175+
const struct sx_pk_ecurve *curve, const uint8_t *workmem,
176+
size_t digestsz, size_t opsz,
177+
struct sx_pk_inops_ecdsa_generate *inputs)
178178
{
179-
*pkreq = sx_pk_acquire_req(SX_PK_CMD_ECDSA_GEN);
180-
if (pkreq->status) {
181-
return pkreq->status;
182-
}
179+
int status = sx_pk_list_ecc_inslots(req, curve, 0, (struct sx_pk_slot *)inputs);
183180

184-
pkreq->status = sx_pk_list_ecc_inslots(pkreq->req, curve, 0, (struct sx_pk_slot *)inputs);
185-
if (pkreq->status) {
186-
return pkreq->status;
181+
if (status) {
182+
return status;
187183
}
188184

189185
ecdsa_write_sk(privkey, inputs->d.addr, opsz);
190186
sx_wrpkmem(inputs->k.addr, workmem + digestsz, opsz);
191187
digest2op(workmem, digestsz, inputs->h.addr, opsz);
192-
sx_pk_run(pkreq->req);
188+
sx_pk_run(req);
193189

194190
return SX_OK;
195191
}
@@ -234,32 +230,44 @@ int cracen_ecdsa_sign_digest(const struct cracen_ecc_priv_key *privkey,
234230
internal_signature.r = signature;
235231
internal_signature.s = signature + opsz;
236232

233+
pkreq = sx_pk_acquire_req(SX_PK_CMD_ECDSA_GEN);
234+
if (pkreq.status) {
235+
sx_pk_release_req(pkreq.req);
236+
return pkreq.status;
237+
}
238+
237239
for (int i = 0; i <= MAX_ECDSA_ATTEMPTS; i++) {
238240
status = cracen_get_rnd_in_range(curve_n, opsz, workmem + digest_length);
239241
if (status != SX_OK) {
242+
sx_pk_release_req(pkreq.req);
240243
return status;
241244
}
242-
status = ecdsa_run_generate_sign(&pkreq, privkey, curve, workmem, digest_length,
243-
opsz, &inputs);
244245

245-
if (status != SX_OK) {
246-
return status;
246+
if (i > 0) {
247+
sx_pk_set_cmd(pkreq.req, SX_PK_CMD_ECDSA_GEN);
247248
}
248-
status = sx_pk_wait(pkreq.req);
249+
250+
status = ecdsa_run_generate_sign(pkreq.req, privkey, curve, workmem,
251+
digest_length, opsz, &inputs);
249252
if (status != SX_OK) {
250253
sx_pk_release_req(pkreq.req);
254+
return status;
251255
}
252256

257+
status = sx_pk_wait(pkreq.req);
258+
253259
/* SX_ERR_NOT_INVERTIBLE may be due to silexpk countermeasures. */
254260
if ((status == SX_ERR_INVALID_SIGNATURE) || (status == SX_ERR_NOT_INVERTIBLE)) {
255-
sx_pk_release_req(pkreq.req);
256261
if (i == MAX_ECDSA_ATTEMPTS) {
262+
sx_pk_release_req(pkreq.req);
257263
return SX_ERR_TOO_MANY_ATTEMPTS;
258264
}
265+
/* Continue loop to retry */
259266
} else {
260267
break;
261268
}
262269
}
270+
263271
if (status != SX_OK) {
264272
sx_pk_release_req(pkreq.req);
265273
return status;
@@ -439,6 +447,12 @@ int cracen_ecdsa_sign_digest_deterministic(const struct cracen_ecc_priv_key *pri
439447
internal_signature.s = signature + opsz;
440448
memcpy(workmem, digest, digestsz);
441449

450+
pkreq = sx_pk_acquire_req(SX_PK_CMD_ECDSA_GEN);
451+
if (pkreq.status) {
452+
sx_pk_release_req(pkreq.req);
453+
return pkreq.status;
454+
}
455+
442456
do {
443457
hmac_op.deterministic_retries = 0;
444458
hmac_op.step = 0;
@@ -451,20 +465,19 @@ int cracen_ecdsa_sign_digest_deterministic(const struct cracen_ecc_priv_key *pri
451465
blocksz, workmem, &hmac_op,
452466
privkey);
453467
if (status != SX_OK && status != SX_ERR_HW_PROCESSING) {
468+
sx_pk_release_req(pkreq.req);
454469
return status;
455470
}
456471
}
457-
status = ecdsa_run_generate_sign(&pkreq, privkey, curve, workmem, digestsz, opsz,
458-
&inputs);
459472

473+
status = ecdsa_run_generate_sign(pkreq.req, privkey, curve, workmem, digestsz,
474+
opsz, &inputs);
460475
if (status != SX_OK) {
476+
sx_pk_release_req(pkreq.req);
461477
return status;
462478
}
463-
status = sx_pk_wait(pkreq.req);
464479

465-
if (status != SX_OK) {
466-
sx_pk_release_req(pkreq.req);
467-
}
480+
status = sx_pk_wait(pkreq.req);
468481

469482
} while (--hmac_op.attempts &&
470483
(status == SX_ERR_INVALID_SIGNATURE || status == SX_ERR_NOT_INVERTIBLE));

0 commit comments

Comments
 (0)