@@ -49,15 +49,21 @@ static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits)
4949 out [i ] = __swab64 (in [ndigits - 1 - i ]);
5050}
5151
52+ /* compute_ecdh_secret() - function assumes that the private key was
53+ * already set.
54+ * @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
55+ * @public_key: pair's ecc public key.
56+ * secret: memory where the ecdh computed shared secret will be saved.
57+ *
58+ * Return: zero on success; error code in case of error.
59+ */
5260int compute_ecdh_secret (struct crypto_kpp * tfm , const u8 public_key [64 ],
53- const u8 private_key [ 32 ], u8 secret [32 ])
61+ u8 secret [32 ])
5462{
5563 struct kpp_request * req ;
56- struct ecdh p ;
64+ u8 * tmp ;
5765 struct ecdh_completion result ;
5866 struct scatterlist src , dst ;
59- u8 * tmp , * buf ;
60- unsigned int buf_len ;
6167 int err ;
6268
6369 tmp = kmalloc (64 , GFP_KERNEL );
@@ -72,28 +78,6 @@ int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 public_key[64],
7278
7379 init_completion (& result .completion );
7480
75- /* Security Manager Protocol holds digits in litte-endian order
76- * while ECC API expect big-endian data
77- */
78- swap_digits ((u64 * )private_key , (u64 * )tmp , 4 );
79- p .key = (char * )tmp ;
80- p .key_size = 32 ;
81- /* Set curve_id */
82- p .curve_id = ECC_CURVE_NIST_P256 ;
83- buf_len = crypto_ecdh_key_len (& p );
84- buf = kmalloc (buf_len , GFP_KERNEL );
85- if (!buf ) {
86- err = - ENOMEM ;
87- goto free_req ;
88- }
89-
90- crypto_ecdh_encode_key (buf , buf_len , & p );
91-
92- /* Set A private Key */
93- err = crypto_kpp_set_secret (tfm , (void * )buf , buf_len );
94- if (err )
95- goto free_all ;
96-
9781 swap_digits ((u64 * )public_key , (u64 * )tmp , 4 ); /* x */
9882 swap_digits ((u64 * )& public_key [32 ], (u64 * )& tmp [32 ], 4 ); /* y */
9983
@@ -118,26 +102,76 @@ int compute_ecdh_secret(struct crypto_kpp *tfm, const u8 public_key[64],
118102 memcpy (secret , tmp , 32 );
119103
120104free_all :
121- kzfree (buf );
122- free_req :
123105 kpp_request_free (req );
124106free_tmp :
125107 kzfree (tmp );
126108 return err ;
127109}
128110
129- int generate_ecdh_keys (struct crypto_kpp * tfm , u8 public_key [64 ],
130- u8 private_key [32 ])
111+ /* set_ecdh_privkey() - set or generate ecc private key.
112+ *
113+ * Function generates an ecc private key in the crypto subsystem when receiving
114+ * a NULL private key or sets the received key when not NULL.
115+ *
116+ * @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
117+ * @private_key: user's ecc private key. When not NULL, the key is expected
118+ * in little endian format.
119+ *
120+ * Return: zero on success; error code in case of error.
121+ */
122+ int set_ecdh_privkey (struct crypto_kpp * tfm , const u8 private_key [32 ])
123+ {
124+ u8 * buf , * tmp = NULL ;
125+ unsigned int buf_len ;
126+ int err ;
127+ struct ecdh p = {0 };
128+
129+ p .curve_id = ECC_CURVE_NIST_P256 ;
130+
131+ if (private_key ) {
132+ tmp = kmalloc (32 , GFP_KERNEL );
133+ if (!tmp )
134+ return - ENOMEM ;
135+ swap_digits ((u64 * )private_key , (u64 * )tmp , 4 );
136+ p .key = tmp ;
137+ p .key_size = 32 ;
138+ }
139+
140+ buf_len = crypto_ecdh_key_len (& p );
141+ buf = kmalloc (buf_len , GFP_KERNEL );
142+ if (!buf ) {
143+ err = - ENOMEM ;
144+ goto free_tmp ;
145+ }
146+
147+ err = crypto_ecdh_encode_key (buf , buf_len , & p );
148+ if (err )
149+ goto free_all ;
150+
151+ err = crypto_kpp_set_secret (tfm , buf , buf_len );
152+ /* fall through */
153+ free_all :
154+ kzfree (buf );
155+ free_tmp :
156+ kzfree (tmp );
157+ return err ;
158+ }
159+
160+ /* generate_ecdh_public_key() - function assumes that the private key was
161+ * already set.
162+ *
163+ * @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
164+ * @public_key: memory where the computed ecc public key will be saved.
165+ *
166+ * Return: zero on success; error code in case of error.
167+ */
168+ int generate_ecdh_public_key (struct crypto_kpp * tfm , u8 public_key [64 ])
131169{
132170 struct kpp_request * req ;
133- struct ecdh p ;
171+ u8 * tmp ;
134172 struct ecdh_completion result ;
135173 struct scatterlist dst ;
136- u8 * tmp , * buf ;
137- unsigned int buf_len ;
138174 int err ;
139- const unsigned short max_tries = 16 ;
140- unsigned short tries = 0 ;
141175
142176 tmp = kmalloc (64 , GFP_KERNEL );
143177 if (!tmp )
@@ -150,63 +184,47 @@ int generate_ecdh_keys(struct crypto_kpp *tfm, u8 public_key[64],
150184 }
151185
152186 init_completion (& result .completion );
187+ sg_init_one (& dst , tmp , 64 );
188+ kpp_request_set_input (req , NULL , 0 );
189+ kpp_request_set_output (req , & dst , 64 );
190+ kpp_request_set_callback (req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
191+ ecdh_complete , & result );
153192
154- /* Set curve_id */
155- p .curve_id = ECC_CURVE_NIST_P256 ;
156- p .key_size = 32 ;
157- buf_len = crypto_ecdh_key_len (& p );
158- buf = kmalloc (buf_len , GFP_KERNEL );
159- if (!buf )
160- goto free_req ;
161-
162- do {
163- if (tries ++ >= max_tries )
164- goto free_all ;
165-
166- /* Set private Key */
167- p .key = (char * )private_key ;
168- crypto_ecdh_encode_key (buf , buf_len , & p );
169- err = crypto_kpp_set_secret (tfm , buf , buf_len );
170- if (err )
171- goto free_all ;
172-
173- sg_init_one (& dst , tmp , 64 );
174- kpp_request_set_input (req , NULL , 0 );
175- kpp_request_set_output (req , & dst , 64 );
176- kpp_request_set_callback (req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
177- ecdh_complete , & result );
178-
179- err = crypto_kpp_generate_public_key (req );
180-
181- if (err == - EINPROGRESS ) {
182- wait_for_completion (& result .completion );
183- err = result .err ;
184- }
185-
186- /* Private key is not valid. Regenerate */
187- if (err == - EINVAL )
188- continue ;
189-
190- if (err < 0 )
191- goto free_all ;
192- else
193- break ;
194-
195- } while (true);
196-
197- /* Keys are handed back in little endian as expected by Security
198- * Manager Protocol
193+ err = crypto_kpp_generate_public_key (req );
194+ if (err == - EINPROGRESS ) {
195+ wait_for_completion (& result .completion );
196+ err = result .err ;
197+ }
198+ if (err < 0 )
199+ goto free_all ;
200+
201+ /* The public key is handed back in little endian as expected by
202+ * the Security Manager Protocol.
199203 */
200204 swap_digits ((u64 * )tmp , (u64 * )public_key , 4 ); /* x */
201205 swap_digits ((u64 * )& tmp [32 ], (u64 * )& public_key [32 ], 4 ); /* y */
202- swap_digits ((u64 * )private_key , (u64 * )tmp , 4 );
203- memcpy (private_key , tmp , 32 );
204206
205207free_all :
206- kzfree (buf );
207- free_req :
208208 kpp_request_free (req );
209209free_tmp :
210210 kfree (tmp );
211211 return err ;
212212}
213+
214+ /* generate_ecdh_keys() - generate ecc key pair.
215+ *
216+ * @tfm: KPP tfm handle allocated with crypto_alloc_kpp().
217+ * @public_key: memory where the computed ecc public key will be saved.
218+ *
219+ * Return: zero on success; error code in case of error.
220+ */
221+ int generate_ecdh_keys (struct crypto_kpp * tfm , u8 public_key [64 ])
222+ {
223+ int err ;
224+
225+ err = set_ecdh_privkey (tfm , NULL );
226+ if (err )
227+ return err ;
228+
229+ return generate_ecdh_public_key (tfm , public_key );
230+ }
0 commit comments