1 /*
2 * Copyright (C) 2017 - This file is part of libecc project
3 *
4 * Authors:
5 * Ryad BENADJILA <ryadbenadjila@gmail.com>
6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8 *
9 * Contributors:
10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12 *
13 * This software is licensed under a dual BSD and GPL v2 license.
14 * See LICENSE file at the root folder of the project.
15 */
16 #include <libecc/sig/ec_key.h>
17 #include <libecc/sig/sig_algs.h>
18 #include <libecc/curves/curves.h>
19
20 /*
21 * Check if given private key 'A' has been initialized. Returns 0 on success,
22 * -1 on error
23 */
priv_key_check_initialized(const ec_priv_key * A)24 int priv_key_check_initialized(const ec_priv_key *A)
25 {
26 int ret = 0;
27
28 MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) && (A->params != NULL)), ret, err);
29
30 err:
31 return ret;
32 }
33
34 /*
35 * Same as previous but also verifies that the signature algorithm type does
36 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error.
37 */
priv_key_check_initialized_and_type(const ec_priv_key * A,ec_alg_type alg_type)38 int priv_key_check_initialized_and_type(const ec_priv_key *A,
39 ec_alg_type alg_type)
40 {
41 int ret = 0;
42
43 MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) &&
44 (A->params != NULL) && (A->key_type == alg_type)), ret, err);
45
46 err:
47 return ret;
48 }
49
50 /*
51 * Import a private key from a buffer with known EC parameters and algorithm
52 * Note that no sanity check is performed by the function to verify key
53 * is valid for params. Also note that no deep copy of pointed params is
54 * performed. The function returns 0 on success, -1 on error.
55 */
ec_priv_key_import_from_buf(ec_priv_key * priv_key,const ec_params * params,const u8 * priv_key_buf,u8 priv_key_buf_len,ec_alg_type ec_key_alg)56 int ec_priv_key_import_from_buf(ec_priv_key *priv_key,
57 const ec_params *params,
58 const u8 *priv_key_buf, u8 priv_key_buf_len,
59 ec_alg_type ec_key_alg)
60 {
61 int ret;
62
63 MUST_HAVE((priv_key != NULL), ret, err);
64
65 ret = nn_init_from_buf(&(priv_key->x), priv_key_buf, priv_key_buf_len); EG(ret, err);
66
67 /* Set key type and pointer to EC params */
68 priv_key->key_type = ec_key_alg;
69 priv_key->params = (const ec_params *)params;
70 priv_key->magic = PRIV_KEY_MAGIC;
71
72 err:
73 return ret;
74 }
75
76 /*
77 * Export a private key 'priv_key' to a buffer 'priv_key_buf' of length
78 * 'priv_key_buf_len'. The function returns 0 on sucess, -1 on error.
79 */
ec_priv_key_export_to_buf(const ec_priv_key * priv_key,u8 * priv_key_buf,u8 priv_key_buf_len)80 int ec_priv_key_export_to_buf(const ec_priv_key *priv_key, u8 *priv_key_buf,
81 u8 priv_key_buf_len)
82 {
83 int ret;
84 bitcnt_t blen;
85
86 ret = priv_key_check_initialized(priv_key); EG(ret, err);
87
88 /*
89 * Check that there is enough room to export our private key without
90 * losing information.
91 */
92 ret = nn_bitlen(&(priv_key->x), &blen); EG(ret, err);
93 MUST_HAVE(((8 * (u32)priv_key_buf_len) >= (u32)blen), ret, err);
94
95 /* Export our private key */
96 ret = nn_export_to_buf(priv_key_buf, priv_key_buf_len, &(priv_key->x));
97
98 err:
99 return ret;
100 }
101
102 /*
103 * Check if given public key 'A' has been initialized. Returns 0 on success,
104 * -1 on error
105 */
pub_key_check_initialized(const ec_pub_key * A)106 int pub_key_check_initialized(const ec_pub_key *A)
107 {
108 int ret = 0;
109
110 MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) && (A->params != NULL)), ret, err);
111
112 err:
113 return ret;
114 }
115
116 /*
117 * Same as previous but also verifies that the signature algorithm type does
118 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error.
119 */
pub_key_check_initialized_and_type(const ec_pub_key * A,ec_alg_type alg_type)120 int pub_key_check_initialized_and_type(const ec_pub_key *A,
121 ec_alg_type alg_type)
122 {
123 int ret = 0;
124
125 MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) &&
126 (A->params != NULL) && (A->key_type == alg_type)), ret, err);
127
128 err:
129 return ret;
130 }
131
132 /*
133 * Import a public key from a buffer with known EC parameters and algorithm
134 * Note that no sanity check is performed by the function to verify key
135 * is valid for params. Also note that no deep copy of pointed params is
136 * performed. The buffer contains projective point coordinates. The function
137 * returns 0 on success, -1 on error.
138 */
ec_pub_key_import_from_buf(ec_pub_key * pub_key,const ec_params * params,const u8 * pub_key_buf,u8 pub_key_buf_len,ec_alg_type ec_key_alg)139 int ec_pub_key_import_from_buf(ec_pub_key *pub_key, const ec_params *params,
140 const u8 *pub_key_buf, u8 pub_key_buf_len,
141 ec_alg_type ec_key_alg)
142 {
143 int ret, isone, check;
144
145 MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err);
146
147 /* Import the projective point */
148 ret = prj_pt_import_from_buf(&(pub_key->y),
149 pub_key_buf, pub_key_buf_len,
150 (ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err);
151
152 /* If the cofactor of the curve is not 1, we check that
153 * our public key is indeed in the sub-group generated by
154 * our generator.
155 * NOTE: this is indeed a 'costly' operation, but it is necessary
156 * when we do not trust the public key that is provided, which can
157 * be the case in some protocols.
158 */
159 ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err);
160 if (!isone) {
161 ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err);
162 MUST_HAVE(check, ret, err);
163 }
164
165 /* Set key type and pointer to EC params */
166 pub_key->key_type = ec_key_alg;
167 pub_key->params = (const ec_params *)params;
168 pub_key->magic = PUB_KEY_MAGIC;
169
170 err:
171 return ret;
172 }
173
174 /*
175 * Import a public key from a buffer with known EC parameters and algorithm
176 * Note that no sanity check is performed by the function to verify key
177 * is valid for params. Also note that no deep copy of pointed params is
178 * performed. The buffer contains affine point coordinates. The function
179 * returns 0 on success, -1 on error.
180 */
ec_pub_key_import_from_aff_buf(ec_pub_key * pub_key,const ec_params * params,const u8 * pub_key_buf,u8 pub_key_buf_len,ec_alg_type ec_key_alg)181 int ec_pub_key_import_from_aff_buf(ec_pub_key *pub_key, const ec_params *params,
182 const u8 *pub_key_buf, u8 pub_key_buf_len,
183 ec_alg_type ec_key_alg)
184 {
185 int ret, isone, check;
186
187 MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err);
188
189 /* Import the projective point */
190 ret = prj_pt_import_from_aff_buf(&(pub_key->y),
191 pub_key_buf, pub_key_buf_len,
192 (ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err);
193
194 /* If the cofactor of the curve is not 1, we check that
195 * our public key is indeed in the sub-group generated by
196 * our generator.
197 * NOTE: this is indeed a 'costly' operation, but it is necessary
198 * when we do not trust the public key that is provided, which can
199 * be the case in some protocols.
200 */
201 ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err);
202 if (!isone){
203 ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err);
204 MUST_HAVE(check, ret, err);
205 }
206
207 /* Set key type and pointer to EC params */
208 pub_key->key_type = ec_key_alg;
209 pub_key->params = (const ec_params *)params;
210 pub_key->magic = PUB_KEY_MAGIC;
211
212 err:
213 return ret;
214 }
215
216 /*
217 * Export a public key to a projective point buffer. The function returns 0 on
218 * success, -1 on error.
219 */
ec_pub_key_export_to_buf(const ec_pub_key * pub_key,u8 * pub_key_buf,u8 pub_key_buf_len)220 int ec_pub_key_export_to_buf(const ec_pub_key *pub_key, u8 *pub_key_buf,
221 u8 pub_key_buf_len)
222 {
223 int ret;
224
225 ret = pub_key_check_initialized(pub_key); EG(ret, err);
226 ret = prj_pt_export_to_buf(&(pub_key->y), pub_key_buf, pub_key_buf_len);
227
228 err:
229 return ret;
230 }
231
232 /*
233 * Export a public key to an affine point buffer. The function returns 0 on
234 * success, -1 on error.
235 */
ec_pub_key_export_to_aff_buf(const ec_pub_key * pub_key,u8 * pub_key_buf,u8 pub_key_buf_len)236 int ec_pub_key_export_to_aff_buf(const ec_pub_key *pub_key, u8 *pub_key_buf,
237 u8 pub_key_buf_len)
238 {
239 int ret;
240
241 ret = pub_key_check_initialized(pub_key); EG(ret, err);
242 ret = prj_pt_export_to_aff_buf(&(pub_key->y), pub_key_buf,
243 pub_key_buf_len);
244
245 err:
246 return ret;
247 }
248
249 /*
250 * Check if given key pair 'A' has been initialized. Returns 0 on success,
251 * -1 on error
252 */
key_pair_check_initialized(const ec_key_pair * A)253 int key_pair_check_initialized(const ec_key_pair *A)
254 {
255 int ret;
256
257 MUST_HAVE((A != NULL), ret, err);
258
259 ret = priv_key_check_initialized(&A->priv_key); EG(ret, err);
260 ret = pub_key_check_initialized(&A->pub_key);
261
262 err:
263 return ret;
264 }
265
266 /*
267 * Same as previous but also verifies that the signature algorithm type does
268 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error.
269 */
key_pair_check_initialized_and_type(const ec_key_pair * A,ec_alg_type alg_type)270 int key_pair_check_initialized_and_type(const ec_key_pair *A,
271 ec_alg_type alg_type)
272 {
273 int ret;
274
275 MUST_HAVE((A != NULL), ret, err);
276
277 ret = priv_key_check_initialized_and_type(&A->priv_key, alg_type); EG(ret, err);
278 ret = pub_key_check_initialized_and_type(&A->pub_key, alg_type);
279
280 err:
281 return ret;
282 }
283
284 /*
285 * Import a key pair from a buffer representing the private key. The associated
286 * public key is computed from the private key. The function returns 0 on
287 * success, -1 on error.
288 */
ec_key_pair_import_from_priv_key_buf(ec_key_pair * kp,const ec_params * params,const u8 * priv_key,u8 priv_key_len,ec_alg_type ec_key_alg)289 int ec_key_pair_import_from_priv_key_buf(ec_key_pair *kp,
290 const ec_params *params,
291 const u8 *priv_key, u8 priv_key_len,
292 ec_alg_type ec_key_alg)
293 {
294 int ret;
295
296 MUST_HAVE((kp != NULL), ret, err);
297
298 /* Import private key */
299 ret = ec_priv_key_import_from_buf(&(kp->priv_key), params, priv_key,
300 priv_key_len, ec_key_alg); EG(ret, err);
301 /* Generate associated public key. */
302 ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key));
303
304 err:
305 return ret;
306 }
307
308 /*
309 * Import a structured private key to buffer. The structure allows some sanity
310 * checks. The function returns 0 on success, -1 on error.
311 */
ec_structured_priv_key_import_from_buf(ec_priv_key * priv_key,const ec_params * params,const u8 * priv_key_buf,u8 priv_key_buf_len,ec_alg_type ec_key_alg)312 int ec_structured_priv_key_import_from_buf(ec_priv_key *priv_key,
313 const ec_params *params,
314 const u8 *priv_key_buf,
315 u8 priv_key_buf_len,
316 ec_alg_type ec_key_alg)
317 {
318 u8 metadata_len = (3 * sizeof(u8));
319 u8 crv_name_len;
320 u32 len;
321 int ret;
322
323 /* We first pull the metadata, consisting of:
324 * - One byte = the key type (public or private)
325 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...)
326 * - One byte = the curve type (FRP256V1, ...)
327 */
328 MUST_HAVE((priv_key != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err);
329 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
330
331 /* Pull and check the key type */
332 MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err);
333
334 /* Pull and check the algorithm type */
335 MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err);
336
337 /* Pull and check the curve type */
338 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
339 len += 1;
340 MUST_HAVE((len < 256), ret, err);
341 crv_name_len = (u8)len;
342
343 ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]),
344 params->curve_name, crv_name_len); EG(ret, err);
345 ret = ec_priv_key_import_from_buf(priv_key, params,
346 priv_key_buf + metadata_len,
347 (u8)(priv_key_buf_len - metadata_len),
348 ec_key_alg);
349
350 err:
351 return ret;
352 }
353
354 /*
355 * Export a structured private key to buffer. The structure allows some sanity
356 * checks. The function returns 0 on success, -1 on error.
357 */
ec_structured_priv_key_export_to_buf(const ec_priv_key * priv_key,u8 * priv_key_buf,u8 priv_key_buf_len)358 int ec_structured_priv_key_export_to_buf(const ec_priv_key *priv_key,
359 u8 *priv_key_buf, u8 priv_key_buf_len)
360 {
361
362 u8 metadata_len = (3 * sizeof(u8));
363 const u8 *curve_name;
364 u8 curve_name_len;
365 u32 len;
366 ec_curve_type curve_type;
367 int ret;
368
369 ret = priv_key_check_initialized(priv_key); EG(ret, err);
370
371 MUST_HAVE((priv_key_buf != NULL) && (priv_key_buf_len > metadata_len) && (priv_key->params->curve_name != NULL), ret, err);
372
373 /*
374 * We first put the metadata, consisting on:
375 * - One byte = the key type (public or private)
376 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...)
377 * - One byte = the curve type (FRP256V1, ...)
378 */
379
380 /* Push the key type */
381 priv_key_buf[0] = (u8)EC_PRIVKEY;
382
383 /* Push the algorithm type */
384 priv_key_buf[1] = (u8)priv_key->key_type;
385
386 /* Push the curve type */
387 curve_name = priv_key->params->curve_name;
388
389 ret = local_strlen((const char *)curve_name, &len); EG(ret, err);
390 len += 1;
391 MUST_HAVE((len < 256), ret, err);
392 curve_name_len = (u8)len;
393
394 ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err);
395 priv_key_buf[2] = (u8)curve_type;
396
397 /* Push the raw private key buffer */
398 ret = ec_priv_key_export_to_buf(priv_key, priv_key_buf + metadata_len,
399 (u8)(priv_key_buf_len - metadata_len));
400
401 err:
402 return ret;
403 }
404
405 /*
406 * Import a structured pub key from buffer. The structure allows some sanity
407 * checks. The function returns 0 on success, -1 on error.
408 */
ec_structured_pub_key_import_from_buf(ec_pub_key * pub_key,const ec_params * params,const u8 * pub_key_buf,u8 pub_key_buf_len,ec_alg_type ec_key_alg)409 int ec_structured_pub_key_import_from_buf(ec_pub_key *pub_key,
410 const ec_params *params,
411 const u8 *pub_key_buf,
412 u8 pub_key_buf_len,
413 ec_alg_type ec_key_alg)
414 {
415 u8 metadata_len = (3 * sizeof(u8));
416 u8 crv_name_len;
417 u32 len;
418 int ret;
419
420 MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err);
421 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
422
423 /*
424 * We first pull the metadata, consisting of:
425 * - One byte = the key type (public or private)
426 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...)
427 * - One byte = the curve type (FRP256V1, ...)
428 */
429
430 /* Pull and check the key type */
431 MUST_HAVE((EC_PUBKEY == pub_key_buf[0]), ret, err);
432
433 /* Pull and check the algorithm type */
434 MUST_HAVE((ec_key_alg == pub_key_buf[1]), ret, err);
435
436 /* Pull and check the curve type */
437 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
438 len += 1;
439 MUST_HAVE((len < 256), ret, err);
440 crv_name_len = (u8)len;
441
442 ret = ec_check_curve_type_and_name((ec_curve_type) (pub_key_buf[2]),
443 params->curve_name, crv_name_len); EG(ret, err);
444 ret = ec_pub_key_import_from_buf(pub_key, params,
445 pub_key_buf + metadata_len,
446 (u8)(pub_key_buf_len - metadata_len),
447 ec_key_alg);
448
449 err:
450 return ret;
451 }
452
453 /*
454 * Export a structured pubate key to buffer. The structure allows some sanity
455 * checks. The function returns 0 on success, -1 on error.
456 */
ec_structured_pub_key_export_to_buf(const ec_pub_key * pub_key,u8 * pub_key_buf,u8 pub_key_buf_len)457 int ec_structured_pub_key_export_to_buf(const ec_pub_key *pub_key,
458 u8 *pub_key_buf, u8 pub_key_buf_len)
459 {
460 u8 metadata_len = (3 * sizeof(u8));
461 const u8 *curve_name;
462 u8 curve_name_len;
463 u32 len;
464 ec_curve_type curve_type;
465 int ret;
466
467 ret = pub_key_check_initialized(pub_key); EG(ret, err);
468
469 MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err);
470 MUST_HAVE((pub_key->params->curve_name != NULL), ret, err);
471
472 /*
473 * We first put the metadata, consisting of:
474 * - One byte = the key type (public or private)
475 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...)
476 * - One byte = the curve type (FRP256V1, ...)
477 */
478
479 /* Push the key type */
480 pub_key_buf[0] = (u8)EC_PUBKEY;
481
482 /* Push the algorithm type */
483 pub_key_buf[1] = (u8)pub_key->key_type;
484
485 /* Push the curve type */
486 curve_name = pub_key->params->curve_name;
487
488 ret = local_strlen((const char *)curve_name, &len); EG(ret, err);
489 len += 1;
490 MUST_HAVE((len < 256), ret, err);
491 curve_name_len = (u8)len;
492
493 ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err);
494 pub_key_buf[2] = (u8)curve_type;
495
496 /* Push the raw pub key buffer */
497 ret = ec_pub_key_export_to_buf(pub_key, pub_key_buf + metadata_len,
498 (u8)(pub_key_buf_len - metadata_len));
499
500 err:
501 return ret;
502 }
503
504 /*
505 * Import a key pair from a structured private key buffer. The structure allows
506 * some sanity checks. The function returns 0 on success, -1 on error.
507 */
ec_structured_key_pair_import_from_priv_key_buf(ec_key_pair * kp,const ec_params * params,const u8 * priv_key_buf,u8 priv_key_buf_len,ec_alg_type ec_key_alg)508 int ec_structured_key_pair_import_from_priv_key_buf(ec_key_pair *kp,
509 const ec_params *params,
510 const u8 *priv_key_buf,
511 u8 priv_key_buf_len,
512 ec_alg_type ec_key_alg)
513 {
514 u8 metadata_len = (3 * sizeof(u8));
515 u8 crv_name_len;
516 u32 len;
517 int ret;
518
519 MUST_HAVE((kp != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err);
520 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
521
522 /* We first pull the metadata, consisting on:
523 * - One byte = the key type (public or private)
524 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...)
525 * - One byte = the curve type (FRP256V1, ...)
526 */
527
528 /* Pull and check the key type */
529 MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err);
530
531 /* Pull and check the algorithm type */
532 MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err);
533
534 /* Pull and check the curve type */
535 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
536 len += 1;
537 MUST_HAVE((len < 256), ret, err);
538 crv_name_len = (u8)len;
539
540 ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]),
541 params->curve_name, crv_name_len); EG(ret, err);
542 ret = ec_key_pair_import_from_priv_key_buf(kp, params,
543 priv_key_buf + metadata_len,
544 (u8)(priv_key_buf_len - metadata_len),
545 ec_key_alg);
546
547 err:
548 return ret;
549 }
550
551 /*
552 * Import a key pair from a two structured key buffer (private and public one)
553 * The function does not verify the coherency between private and public parts.
554 * The function returns 0 on success, -1 on error.
555 *
556 * NOTE: please use this API with care as it does not check the consistency
557 * between the private and public keys! On one side, this "saves" a costly
558 * scalar multiplication when there is confidence in the source of the buffers,
559 * but on the other side the user of the API MUST check the source (integrity)
560 * of the private/public key pair. If unsure, it is advised to use the
561 * ec_structured_key_pair_import_from_priv_key_buf API that safely derives the
562 * public key from the private key.
563 *
564 */
ec_structured_key_pair_import_from_buf(ec_key_pair * kp,const ec_params * params,const u8 * priv_key_buf,u8 priv_key_buf_len,const u8 * pub_key_buf,u8 pub_key_buf_len,ec_alg_type ec_key_alg)565 int ec_structured_key_pair_import_from_buf(ec_key_pair *kp,
566 const ec_params *params,
567 const u8 *priv_key_buf,
568 u8 priv_key_buf_len,
569 const u8 *pub_key_buf,
570 u8 pub_key_buf_len,
571 ec_alg_type ec_key_alg)
572 {
573 int ret;
574
575 MUST_HAVE((kp != NULL), ret, err);
576
577 ret = ec_structured_pub_key_import_from_buf(&kp->pub_key, params,
578 pub_key_buf,
579 pub_key_buf_len,
580 ec_key_alg); EG(ret, err);
581 ret = ec_structured_priv_key_import_from_buf(&kp->priv_key, params,
582 priv_key_buf,
583 priv_key_buf_len,
584 ec_key_alg);
585
586 err:
587 return ret;
588 }
589
590 /*
591 * Generate a public/private key pair for given signature algorithm, using
592 * given EC params. The function returns 0 on success, -1 on error.
593 */
ec_key_pair_gen(ec_key_pair * kp,const ec_params * params,ec_alg_type ec_key_alg)594 int ec_key_pair_gen(ec_key_pair *kp, const ec_params *params,
595 ec_alg_type ec_key_alg)
596 {
597 int ret;
598
599 MUST_HAVE((kp != NULL) && (params != NULL), ret, err);
600
601 /* Get a random value in ]0,q[ */
602 ret = nn_get_random_mod(&(kp->priv_key.x), &(params->ec_gen_order)); EG(ret, err);
603
604 /* Set key type and pointer to EC params for private key */
605 kp->priv_key.key_type = ec_key_alg;
606 kp->priv_key.params = (const ec_params *)params;
607 kp->priv_key.magic = PRIV_KEY_MAGIC;
608
609 /* Call our private key generation function */
610 ret = gen_priv_key(&(kp->priv_key)); EG(ret, err);
611
612 /* Generate associated public key. */
613 ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key));
614
615 err:
616 if (ret && (kp != NULL)) {
617 IGNORE_RET_VAL(local_memset(kp, 0, sizeof(ec_key_pair)));
618 }
619 return ret;
620 }
621