Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libecc/src/sig/ec_key.c
2066 views
1
/*
2
* Copyright (C) 2017 - This file is part of libecc project
3
*
4
* Authors:
5
* Ryad BENADJILA <[email protected]>
6
* Arnaud EBALARD <[email protected]>
7
* Jean-Pierre FLORI <[email protected]>
8
*
9
* Contributors:
10
* Nicolas VIVET <[email protected]>
11
* Karim KHALFALLAH <[email protected]>
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
622