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
+ #include <zephyr/sys/printk.h>
17
+ #include <zephyr/logging/log.h>
18
+
19
+ #define MAX_ECC_ATTEMPTS 10
20
+ LOG_MODULE_REGISTER (ecc , LOG_LEVEL_DBG );
21
+
22
+ int ecc_create_genpubkey (char * priv_key , char * pub_key , const struct sx_pk_ecurve * curve )
23
+ {
24
+ const char * * outputs ;
25
+ struct sx_pk_acq_req pkreq ;
26
+ struct sx_pk_inops_ecp_mult inputs ;
27
+ int opsz ;
28
+ int status ;
29
+ int attempts = MAX_ECC_ATTEMPTS ;
30
+ for (int i = 0 ; i <= MAX_ECC_ATTEMPTS ; i ++ ) {
31
+ LOG_INF ("ECC test" );
32
+ pkreq = sx_pk_acquire_req (SX_PK_CMD_ECC_PTMUL );
33
+ if (pkreq .status ) {
34
+ return pkreq .status ;
35
+ }
36
+ LOG_INF ("list_ecc_inslots" );
37
+ pkreq .status = sx_pk_list_ecc_inslots (pkreq .req , curve , 0 ,
38
+ (struct sx_pk_slot * )& inputs );
39
+ if (pkreq .status ) {
40
+ return pkreq .status ;
41
+ }
42
+
43
+ opsz = sx_pk_curve_opsize (curve );
44
+ LOG_INF ("curve_opsize" );
45
+
46
+ /* Write the private key (random) into ba414ep device memory */
47
+ sx_wrpkmem (inputs .k .addr , priv_key , opsz );
48
+ sx_pk_write_curve_gen (pkreq .req , curve , inputs .px , inputs .py );
49
+ LOG_INF ("curve_write" );
50
+
51
+ sx_pk_run (pkreq .req );
52
+ LOG_INF ("pk_has_finished" );
53
+
54
+ status = sx_pk_has_finished (pkreq .req );
55
+ LOG_INF ("sx_pk_wait" );
56
+
57
+ status = sx_pk_wait (pkreq .req );
58
+ if (status != SX_OK ) {
59
+ return status ;
60
+ }
61
+ LOG_INF ("output_ops" );
62
+ /* static int on_generated_public(struct sitask *t, struct siwq *wq) */
63
+ outputs = sx_pk_get_output_ops (pkreq .req );
64
+ LOG_INF ("outputs" );
65
+
66
+ /* When countermeasures are used, the operation may fail with error code
67
+ * SX_ERR_NOT_INVERTIBLE. In this case we can try again.
68
+ */
69
+ if (status == SX_ERR_NOT_INVERTIBLE ) {
70
+ sx_pk_release_req (pkreq .req );
71
+ if (i == MAX_ECC_ATTEMPTS ) {
72
+ return SX_ERR_TOO_MANY_ATTEMPTS ;
73
+ }
74
+ } else {
75
+ break ;
76
+ }
77
+
78
+ }
79
+ sx_rdpkmem (pub_key , outputs [0 ], opsz );
80
+
81
+ sx_rdpkmem (pub_key + opsz , outputs [1 ], opsz );
82
+ sx_pk_release_req (pkreq .req );
83
+ LOG_INF ("last wait" );
84
+ return status ;
85
+ }
86
+
87
+ int ecc_create_genprivkey (const struct sx_pk_ecurve * curve ,
88
+ char * priv_key , size_t priv_key_size )
89
+ {
90
+ size_t keysz = (size_t )sx_pk_curve_opsize (curve );
91
+ int status ;
92
+ int opsz = sx_pk_curve_opsize (curve );
93
+ const char * curve_n = sx_pk_curve_order (curve );
94
+
95
+ if (priv_key_size < keysz ) {
96
+ return SX_ERR_OUTPUT_BUFFER_TOO_SMALL ;
97
+ }
98
+
99
+ /* generate private key, a random in [1, n-1], where n is the curve
100
+ * order
101
+ */
102
+ status = rndinrange_create ((const unsigned char * )curve_n , opsz , priv_key );
103
+
104
+ return status ;
105
+ }
0 commit comments