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
17 #include <libecc/libsig.h>
18
19 #ifdef WITH_STDLIB
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #endif
25
26 #define HDR_MAGIC 0x34215609
27
28 typedef enum {
29 IMAGE_TYPE_UNKNOWN = 0,
30 IMAGE_TYPE0 = 1,
31 IMAGE_TYPE1 = 2,
32 IMAGE_TYPE2 = 3,
33 IMAGE_TYPE3 = 4,
34 /* Info: You can add more image header types */
35 } image_type;
36
37 /* Generic header to prepend data */
38 typedef struct {
39 u32 magic; /* header header */
40 u32 type; /* Type of the signed image */
41 u32 version; /* Version */
42 u32 len; /* length of data after header */
43 u32 siglen; /* length of sig (on header + data) */
44 } ATTRIBUTE_PACKED metadata_hdr;
45
46 /* Max stack working buffer size */
47 #define MAX_BUF_LEN 8192
48
49 typedef enum {
50 RAWBIN,
51 DOTH,
52 } export_file_type;
53
export_private_key(FILE * file,const char * name,const ec_priv_key * priv_key,export_file_type file_type)54 ATTRIBUTE_WARN_UNUSED_RET static int export_private_key(FILE * file, const char *name,
55 const ec_priv_key *priv_key,
56 export_file_type file_type)
57 {
58 u8 export_buf_size, priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE];
59 size_t written;
60 int ret;
61 u32 i;
62
63 MUST_HAVE(file != NULL, ret, err);
64
65 ret = priv_key_check_initialized(priv_key);
66 if (ret) {
67 printf("Error checking private key\n");
68 ret = -1;
69 goto err;
70 }
71
72 /* Serialize the private key to a buffer */
73 export_buf_size = EC_STRUCTURED_PRIV_KEY_EXPORT_SIZE(priv_key);
74 ret = ec_structured_priv_key_export_to_buf(priv_key, priv_key_buf,
75 export_buf_size);
76 if (ret) {
77 printf("Error exporting private key to buffer\n");
78 ret = -1;
79 goto err;
80 }
81
82 /* Export the private key to the file */
83 switch (file_type) {
84 case DOTH:
85 MUST_HAVE(name != NULL, ret, err);
86 fprintf(file, "const char %s[] = { ", name);
87 for (i = 0; i < export_buf_size; i++) {
88 fprintf(file, "0x%02x", priv_key_buf[i]);
89 fprintf(file, ", ");
90 }
91 fprintf(file, "};\n");
92 ret = 0;
93 break;
94 case RAWBIN:
95 written = fwrite(priv_key_buf, 1, export_buf_size, file);
96 if(written != export_buf_size){
97 ret = -1;
98 goto err;
99 }
100 ret = 0;
101 break;
102 default:
103 ret = -1;
104 }
105
106 err:
107 return ret;
108 }
109
export_public_key(FILE * file,const char * name,const ec_pub_key * pub_key,export_file_type file_type)110 ATTRIBUTE_WARN_UNUSED_RET static int export_public_key(FILE * file, const char *name,
111 const ec_pub_key *pub_key,
112 export_file_type file_type)
113 {
114 u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE];
115 u8 export_buf_size;
116 int ret;
117 u32 i;
118 size_t written;
119
120 MUST_HAVE(file != NULL, ret, err);
121 ret = pub_key_check_initialized(pub_key);
122 if (ret) {
123 printf("Error checking public key\n");
124 ret = -1;
125 goto err;
126 }
127
128 /* Serialize the public key to a buffer */
129 export_buf_size = EC_STRUCTURED_PUB_KEY_EXPORT_SIZE(pub_key);
130 ret = ec_structured_pub_key_export_to_buf(pub_key, pub_key_buf,
131 export_buf_size);
132 if (ret) {
133 printf("Error exporting public key to buffer\n");
134 ret = -1;
135 goto err;
136 }
137
138 /* Export the public key to the file */
139 switch (file_type) {
140 case DOTH:
141 MUST_HAVE(name != NULL, ret, err);
142 fprintf(file, "const char %s[] = { ", name);
143 for (i = 0; i < export_buf_size; i++) {
144 fprintf(file, "0x%02x", pub_key_buf[i]);
145 if (i != export_buf_size) {
146 fprintf(file, ", ");
147 }
148 }
149 fprintf(file, "};\n");
150 ret = 0;
151 break;
152 case RAWBIN:
153 written = fwrite(pub_key_buf, 1, export_buf_size, file);
154 if(written != export_buf_size){
155 ret = -1;
156 goto err;
157 }
158 ret = 0;
159 break;
160 default:
161 ret = -1;
162 }
163
164 err:
165 return ret;
166 }
167
string_to_params(const char * ec_name,const char * ec_sig_name,ec_alg_type * sig_type,const ec_str_params ** ec_str_p,const char * hash_name,hash_alg_type * hash_type)168 ATTRIBUTE_WARN_UNUSED_RET static int string_to_params(const char *ec_name, const char *ec_sig_name,
169 ec_alg_type * sig_type,
170 const ec_str_params ** ec_str_p,
171 const char *hash_name, hash_alg_type * hash_type)
172 {
173 const ec_str_params *curve_params;
174 const ec_sig_mapping *sm;
175 const hash_mapping *hm;
176 u32 curve_name_len;
177 int ret;
178
179 if (sig_type != NULL) {
180 /* Get sig type from signature alg name */
181 ret = get_sig_by_name(ec_sig_name, &sm);
182 if ((ret) || (!sm)) {
183 ret = -1;
184 printf("Error: signature type %s is unknown!\n",
185 ec_sig_name);
186 goto err;
187 }
188 *sig_type = sm->type;
189 }
190
191 if (ec_str_p != NULL) {
192 /* Get curve params from curve name */
193 ret = local_strlen((const char *)ec_name, &curve_name_len); EG(ret, err);
194 curve_name_len += 1;
195 if(curve_name_len > 255){
196 /* Sanity check */
197 ret = -1;
198 goto err;
199 }
200 ret = ec_get_curve_params_by_name((const u8 *)ec_name,
201 (u8)curve_name_len, &curve_params);
202 if ((ret) || (!curve_params)) {
203 ret = -1;
204 printf("Error: EC curve %s is unknown!\n", ec_name);
205 goto err;
206 }
207 *ec_str_p = curve_params;
208 }
209
210 if (hash_type != NULL) {
211 /* Get hash type from hash alg name */
212 ret = get_hash_by_name(hash_name, &hm);
213 if ((ret) || (!hm)) {
214 ret = -1;
215 printf("Error: hash function %s is unknown!\n",
216 hash_name);
217 goto err;
218 }
219 *hash_type = hm->type;
220 }
221
222 ret = 0;
223
224 err:
225 return ret;
226 }
227
generate_and_export_key_pair(const char * ec_name,const char * ec_sig_name,const char * fname_prefix)228 ATTRIBUTE_WARN_UNUSED_RET static int generate_and_export_key_pair(const char *ec_name,
229 const char *ec_sig_name,
230 const char *fname_prefix)
231 {
232 const ec_str_params *ec_str_p;
233 char fname[MAX_BUF_LEN];
234 char kname[MAX_BUF_LEN];
235 const u16 fname_len = sizeof(fname);
236 const u16 kname_len = sizeof(kname);
237 u16 prefix_len;
238 u32 len;
239 ec_alg_type sig_type;
240 ec_params params;
241 ec_key_pair kp;
242 FILE *file = NULL;
243 int ret;
244
245 MUST_HAVE(ec_name != NULL, ret, err);
246 MUST_HAVE(fname_prefix != NULL, ret, err);
247 MUST_HAVE(ec_sig_name != NULL, ret, err);
248
249 /* Get parameters from pretty names */
250 ret = string_to_params(ec_name, ec_sig_name, &sig_type, &ec_str_p,
251 NULL, NULL);
252 if (ret) {
253 ret = -1;
254 printf("Error: error when importing params\n");
255 goto err;
256 }
257
258 /* Import the parameters */
259 ret = import_params(¶ms, ec_str_p); EG(ret, err);
260
261 /* Generate the key pair */
262 ret = ec_key_pair_gen(&kp, ¶ms, sig_type); EG(ret, err);
263
264 /* Get the unique affine equivalent representation of the projective point for the public key.
265 * This avoids ambiguity when exporting the point, and is mostly here
266 * for compatibility with external libraries.
267 */
268 ret = prj_pt_unique(&(kp.pub_key.y), &(kp.pub_key.y)); EG(ret, err);
269
270 /*************************/
271
272 /* Export the private key to the raw binary file */
273 ret = local_strnlen(fname_prefix, fname_len, &len); EG(ret, err);
274 MUST_HAVE(len <= 0xffff, ret, err);
275 prefix_len = (u16)len;
276 ret = local_memset(fname, 0, fname_len); EG(ret, err);
277 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);
278 ret = local_strncat(fname, "_private_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err);
279 file = fopen(fname, "wb");
280 if (file == NULL) {
281 ret = -1;
282 printf("Error: file %s cannot be opened\n", fname);
283 goto err;
284 }
285
286 ret = export_private_key(file, NULL, &(kp.priv_key), RAWBIN);
287 if (ret) {
288 ret = -1;
289 printf("Error exporting the private key\n");
290 goto err;
291 }
292 ret = fclose(file); EG(ret, err);
293 file = NULL;
294
295 /* Export the private key to the .h file */
296 ret = local_memset(fname, 0, fname_len); EG(ret, err);
297 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);
298 ret = local_strncat(fname, "_private_key.h", (u32)(fname_len - prefix_len)); EG(ret, err);
299 file = fopen(fname, "w");
300 if (file == NULL) {
301 ret = -1;
302 printf("Error: file %s cannot be opened\n", fname);
303 goto err;
304 }
305
306 snprintf(kname, kname_len, "%s_%s_private_key", ec_name, ec_sig_name);
307 ret = export_private_key(file, kname, &(kp.priv_key), DOTH);
308 if (ret) {
309 ret = -1;
310 printf("Error: error exporting the private key\n");
311 goto err;
312 }
313 ret = fclose(file); EG(ret, err);
314 file = NULL;
315
316 /*************************/
317
318 /* Export the public key to the raw binary file */
319 ret = local_memset(fname, 0, fname_len); EG(ret, err);
320 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);
321 ret = local_strncat(fname, "_public_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err);
322 file = fopen(fname, "wb");
323 if (file == NULL) {
324 ret = -1;
325 printf("Error: file %s cannot be opened\n", fname);
326 goto err;
327 }
328 ret = export_public_key(file, NULL, &(kp.pub_key), RAWBIN);
329 if (ret) {
330 ret = -1;
331 printf("Error exporting the public key\n");
332 goto err;
333 }
334 ret = fclose(file); EG(ret, err);
335 file = NULL;
336
337 /* Export the public key to the .h file */
338 ret = local_memset(fname, 0, fname_len); EG(ret, err);
339 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err);
340 ret = local_strncat(fname, "_public_key.h", (u32)(fname_len - prefix_len)); EG(ret, err);
341 file = fopen(fname, "w");
342 if (file == NULL) {
343 ret = -1;
344 printf("Error: file %s cannot be opened\n", fname);
345 goto err;
346 }
347
348 snprintf(kname, kname_len, "%s_%s_public_key", ec_name, ec_sig_name);
349 ret = export_public_key(file, kname, &(kp.pub_key), DOTH);
350 if (ret) {
351 ret = -1;
352 printf("Error exporting the public key\n");
353 goto err;
354 }
355 ret = fclose(file); EG(ret, err);
356 file = NULL;
357
358 ret = 0;
359
360 err:
361 if(file != NULL){
362 if(fclose(file)){
363 ret = -1;
364 }
365 }
366 return ret;
367 }
368
369
store_sig(const char * in_fname,const char * out_fname,const u8 * sig,u32 siglen,ec_alg_type sig_type,hash_alg_type hash_type,const u8 curve_name[MAX_CURVE_NAME_LEN],metadata_hdr * hdr)370 ATTRIBUTE_WARN_UNUSED_RET static int store_sig(const char *in_fname, const char *out_fname,
371 const u8 *sig, u32 siglen,
372 ec_alg_type sig_type, hash_alg_type hash_type,
373 const u8 curve_name[MAX_CURVE_NAME_LEN],
374 metadata_hdr * hdr)
375 {
376 FILE *in_file = NULL, *out_file = NULL;
377 u8 buf[MAX_BUF_LEN];
378 size_t read, written;
379 int ret;
380
381 MUST_HAVE((in_fname != NULL), ret, err);
382 MUST_HAVE((out_fname != NULL), ret, err);
383 MUST_HAVE((sig != NULL), ret, err);
384 MUST_HAVE((curve_name != NULL), ret, err);
385 MUST_HAVE((hdr != NULL), ret, err);
386 #if (MAX_BUF_LEN <= 255)
387 /* No need to check this is sizeof(buf) exceeds 256.
388 * (avoids -Werror,-Wtautological-constant-out-of-range-compare)
389 */
390 MUST_HAVE(EC_STRUCTURED_SIG_EXPORT_SIZE(siglen) <= sizeof(buf), ret, err);
391 #endif
392 /* Import the data from the input file */
393 in_file = fopen(in_fname, "rb");
394 if (in_file == NULL) {
395 ret = -1;
396 printf("Error: file %s cannot be opened\n", in_fname);
397 goto err;
398 }
399 out_file = fopen(out_fname, "wb");
400 if (out_file == NULL) {
401 ret = -1;
402 printf("Error: file %s cannot be opened\n", out_fname);
403 goto err;
404 }
405 if (hdr != NULL) {
406 /* Write the metadata header as a prepending information */
407 written = fwrite(hdr, 1, sizeof(metadata_hdr), out_file);
408 if (written != sizeof(metadata_hdr)) {
409 ret = -1;
410 goto err;
411 }
412 }
413
414 while (1) {
415 read = fread(buf, 1, sizeof(buf), in_file);
416 written = fwrite(buf, 1, read, out_file);
417 if (written != read) {
418 ret = -1;
419 printf("Error: error when writing to %s\n",
420 out_fname);
421 goto err;
422 }
423 if (read != sizeof(buf)) {
424 if (feof(in_file)) {
425 /* EOF */
426 break;
427 } else {
428 ret = -1;
429 printf("Error: error when reading from %s\n",
430 in_fname);
431 goto err;
432 }
433 }
434
435 }
436
437 /* Compute the structured signature */
438 ret = ec_structured_sig_export_to_buf(sig, siglen, buf, sizeof(buf),
439 sig_type, hash_type, curve_name);
440 if (ret) {
441 ret = -1;
442 printf("Error: error when exporting signature to structured buffer\n");
443 goto err;
444 }
445 /* Store the signature buffer */
446 written =
447 fwrite(buf, 1, EC_STRUCTURED_SIG_EXPORT_SIZE(siglen),
448 out_file);
449 if (written != EC_STRUCTURED_SIG_EXPORT_SIZE(siglen)) {
450 ret = -1;
451 printf("Error: error when writing to %s\n", out_fname);
452 goto err;
453 }
454
455 ret = 0;
456
457 err:
458 if(in_file != NULL){
459 if(fclose(in_file)){
460 ret = -1;
461 }
462 }
463 if(out_file != NULL){
464 if(fclose(out_file)){
465 ret = -1;
466 }
467 }
468 return ret;
469 }
470
471 /* Get the raw size of a file */
get_file_size(const char * in_fname,size_t * outsz)472 ATTRIBUTE_WARN_UNUSED_RET static int get_file_size(const char *in_fname, size_t *outsz)
473 {
474 FILE *in_file = NULL;
475 long size;
476 int ret;
477
478 MUST_HAVE(outsz != NULL, ret, err);
479 MUST_HAVE(in_fname != NULL, ret, err);
480
481 *outsz = 0;
482
483 in_file = fopen(in_fname, "rb");
484 if (in_file == NULL) {
485 ret = -1;
486 printf("Error: file %s cannot be opened\n", in_fname);
487 goto err;
488 }
489 /* Compute the size of the file */
490 if (fseek(in_file, 0L, SEEK_END)) {
491 ret = -1;
492 printf("Error: file %s cannot be seeked\n", in_fname);
493 goto err;
494 }
495 size = ftell(in_file);
496 if (size < 0) {
497 ret = -1;
498 printf("Error: cannot compute file %s size\n", in_fname);
499 goto err;
500 }
501 /* Check overflow */
502 if ((u64)size > (u64)(0xffffffff)) {
503 ret = -1;
504 printf("Error: file %s size %ld overflow (>= 2^32)\n",
505 in_fname, size);
506 goto err;
507 }
508
509 *outsz = (u32)size;
510 ret = 0;
511
512 err:
513 if(in_file != NULL){
514 if(fclose(in_file)){
515 ret = -1;
516 }
517 }
518 return ret;
519 }
520
521 /* Generate a proper handler from a given type and other information */
generate_metadata_hdr(metadata_hdr * hdr,const char * hdr_type,const char * version,size_t len,u8 siglen)522 ATTRIBUTE_WARN_UNUSED_RET static int generate_metadata_hdr(metadata_hdr * hdr, const char *hdr_type,
523 const char *version, size_t len, u8 siglen)
524 {
525 unsigned long ver;
526 char *endptr; /* for strtoul() */
527 int ret, check;
528
529 MUST_HAVE((hdr != NULL), ret, err);
530 MUST_HAVE((hdr_type != NULL), ret, err);
531 MUST_HAVE((version != NULL), ret, err);
532
533 /* The magic value */
534 hdr->magic = HDR_MAGIC;
535
536 /* The given version */
537 #ifdef WITH_STDLIB
538 errno = 0;
539 #endif
540 ver = strtoul(version, &endptr, 0);
541 #ifdef WITH_STDLIB
542 if(errno){
543 ret = -1;
544 printf("Error: error in strtoul\n");
545 goto err;
546 }
547 #endif
548 if (*endptr != '\0') {
549 ret = -1;
550 printf("Error: error getting provided version %s\n", version);
551 goto err;
552 }
553 if ((ver & 0xffffffff) != ver) {
554 ret = -1;
555 printf("Error: provided version %s is too long!\n", version);
556 goto err;
557 }
558 hdr->version = (u32)ver;
559
560 /* The image type */
561 hdr->type = IMAGE_TYPE_UNKNOWN;
562 ret = are_str_equal(hdr_type, "IMAGE_TYPE0", &check); EG(ret, err);
563 if (check) {
564 hdr->type = IMAGE_TYPE0;
565 }
566 ret = are_str_equal(hdr_type, "IMAGE_TYPE1", &check); EG(ret, err);
567 if (check) {
568 hdr->type = IMAGE_TYPE1;
569 }
570 ret = are_str_equal(hdr_type, "IMAGE_TYPE2", &check); EG(ret, err);
571 if (check) {
572 hdr->type = IMAGE_TYPE2;
573 }
574 ret = are_str_equal(hdr_type, "IMAGE_TYPE3", &check); EG(ret, err);
575 if (check) {
576 hdr->type = IMAGE_TYPE3;
577 }
578 if (hdr->type == IMAGE_TYPE_UNKNOWN) {
579 ret = -1;
580 printf("Error: unknown header type %s\n", hdr_type);
581 goto err;
582 }
583
584 /* The length without the signature */
585 if ((len & 0xffffffff) != len) {
586 ret = -1;
587 printf("Error: provided length value %lu is too long!\n", (unsigned long)len);
588 goto err;
589 }
590 hdr->len = (u32)len;
591
592 /* The signature length */
593 hdr->siglen = siglen;
594
595 ret = 0;
596
597 err:
598 return ret;
599 }
600
601 /* Warn the user that the provided ancillary data won't be used
602 * if the algorithm does not need them.
603 */
check_ancillary_data(const char * adata,ec_alg_type sig_type,const char * sig_name,int * check)604 ATTRIBUTE_WARN_UNUSED_RET static int check_ancillary_data(const char *adata, ec_alg_type sig_type, const char *sig_name, int *check)
605 {
606 int ret;
607
608 MUST_HAVE(check != NULL, ret, err);
609 MUST_HAVE(adata != NULL, ret, err);
610 MUST_HAVE(sig_name != NULL, ret, err);
611 MUST_HAVE(sig_type != UNKNOWN_ALG, ret, err);
612
613 (*check) = 0;
614
615 #if defined(WITH_SIG_EDDSA25519)
616 if(sig_type == EDDSA25519CTX){
617 (*check) = 1;
618 }
619 #endif
620 #if defined(WITH_SIG_EDDSA448)
621 if(sig_type == EDDSA448){
622 (*check) = 1;
623 }
624 #endif
625 #if defined(WITH_SIG_SM2)
626 if(sig_type == SM2){
627 (*check) = 1;
628 }
629 #endif
630 if((*check) == 0){
631 printf("Warning: you have provided optional ancillary data "\
632 "with a signature algorithm %s that does not need it! "\
633 "This data is ignored.\n", sig_name);
634 }
635
636 ret = 0;
637
638 err:
639 return ret;
640 }
641
642 /*
643 * Sign data from file and append signature
644 */
sign_bin_file(const char * ec_name,const char * ec_sig_name,const char * hash_algorithm,const char * in_fname,const char * in_key_fname,const char * out_fname,const char * hdr_type,const char * version,const char * adata,u16 adata_len)645 ATTRIBUTE_WARN_UNUSED_RET static int sign_bin_file(const char *ec_name, const char *ec_sig_name,
646 const char *hash_algorithm, const char *in_fname,
647 const char *in_key_fname,
648 const char *out_fname, const char *hdr_type,
649 const char *version, const char *adata, u16 adata_len)
650 {
651 u8 sig[EC_MAX_SIGLEN];
652 u8 buf[MAX_BUF_LEN];
653 u8 siglen;
654 FILE *in_file = NULL;
655 ec_key_pair key_pair;
656 FILE *in_key_file = NULL;
657 FILE *out_file = NULL;
658 const ec_str_params *ec_str_p;
659 ec_params params;
660 int ret, check;
661 ec_alg_type sig_type;
662 hash_alg_type hash_type;
663 u8 priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE];
664 u8 priv_key_buf_len;
665 size_t raw_data_len;
666 metadata_hdr hdr;
667 size_t read, to_read;
668 int eof;
669 u8 *allocated_buff = NULL;
670 struct ec_sign_context sig_ctx;
671
672 MUST_HAVE(ec_name != NULL, ret, err);
673 MUST_HAVE(ec_sig_name != NULL, ret, err);
674 MUST_HAVE(hash_algorithm != NULL, ret, err);
675 MUST_HAVE(in_fname != NULL, ret, err);
676 MUST_HAVE(in_key_fname != NULL, ret, err);
677 MUST_HAVE(out_fname != NULL, ret, err);
678
679 /************************************/
680 /* Get parameters from pretty names */
681 if (string_to_params
682 (ec_name, ec_sig_name, &sig_type, &ec_str_p, hash_algorithm,
683 &hash_type)) {
684 ret = -1;
685 goto err;
686 }
687 if(adata != NULL){
688 /* Check if ancillary data will be used */
689 ret = check_ancillary_data(adata, sig_type, ec_sig_name, &check); EG(ret, err);
690 }
691 /* Import the parameters */
692 ret = import_params(¶ms, ec_str_p); EG(ret, err);
693
694 /************************************/
695 /* Import the private key from the file */
696 in_key_file = fopen(in_key_fname, "rb");
697 if (in_key_file == NULL) {
698 ret = -1;
699 printf("Error: file %s cannot be opened\n", in_key_fname);
700 goto err;
701 }
702 priv_key_buf_len = (u8)fread(priv_key_buf, 1, sizeof(priv_key_buf),
703 in_key_file);
704 ret = ec_structured_key_pair_import_from_priv_key_buf(&key_pair,
705 ¶ms,
706 priv_key_buf,
707 priv_key_buf_len,
708 sig_type);
709 if (ret) {
710 ret = -1;
711 printf("Error: error when importing key pair from %s\n",
712 in_key_fname);
713 goto err;
714 }
715
716 ret = get_file_size(in_fname, &raw_data_len);
717 if (ret) {
718 ret = -1;
719 printf("Error: cannot retrieve file %s size\n", in_fname);
720 goto err;
721 }
722 if(raw_data_len == 0){
723 ret = -1;
724 printf("Error: file %s seems to be empty!\n", in_fname);
725 goto err;
726 }
727 ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen);
728 if (ret) {
729 ret = -1;
730 printf("Error getting effective signature length from %s\n",
731 (const char *)(ec_str_p->name->buf));
732 goto err;
733 }
734
735 /* Structured export case, we forge a header */
736 if((hdr_type != NULL) && (version != NULL)){
737 /************************************/
738 /* Forge the header */
739 ret = generate_metadata_hdr(&hdr, hdr_type, version, raw_data_len,
740 EC_STRUCTURED_SIG_EXPORT_SIZE(siglen));
741
742 if (ret) {
743 ret = -1;
744 printf("Error: error when generating metadata\n");
745 goto err;
746 }
747 }
748
749 /* Check if we support streaming */
750 ret = is_sign_streaming_mode_supported(sig_type, &check); EG(ret, err);
751 if(check){
752 /**** We support streaming mode ****/
753 /*
754 * Initialize signature context and start signature computation
755 * with generated metadata header.
756 */
757 ret = ec_sign_init(&sig_ctx, &key_pair, sig_type, hash_type, (const u8*)adata, adata_len);
758 if (ret) {
759 ret = -1;
760 printf("Error: error when signing\n");
761 goto err;
762 }
763
764 /* Structured export case, we prepend the header in the signature */
765 if((hdr_type != NULL) && (version != NULL)){
766 ret = ec_sign_update(&sig_ctx, (const u8 *)&hdr, sizeof(metadata_hdr));
767 if (ret) {
768 ret = -1;
769 printf("Error: error when signing\n");
770 goto err;
771 }
772 }
773
774 /*
775 * Read file content chunk by chunk up to file length, passing each
776 * chunk to signature update function
777 */
778 in_file = fopen(in_fname, "rb");
779 if (in_file == NULL) {
780 ret = -1;
781 printf("Error: file %s cannot be opened\n", in_fname);
782 goto err;
783 }
784
785 eof = 0;
786 clearerr(in_file);
787 while (raw_data_len && !eof) {
788 to_read =
789 (raw_data_len <
790 sizeof(buf)) ? raw_data_len : sizeof(buf);
791 memset(buf, 0, sizeof(buf));
792 read = fread(buf, 1, to_read, in_file);
793 if (read != to_read) {
794 /* Check if this was EOF */
795 ret = feof(in_file);
796 clearerr(in_file);
797 if (ret) {
798 eof = 1;
799 }
800 }
801
802 if (read > raw_data_len) {
803 /* we read more than expected: leave! */
804 break;
805 }
806
807 raw_data_len -= read;
808
809 ret = ec_sign_update(&sig_ctx, buf, (u32)read);
810 if (ret) {
811 break;
812 }
813 }
814
815 if (raw_data_len) {
816 ret = -1;
817 printf("Error: unable to read full file content\n");
818 goto err;
819 }
820
821 /* We can now complete signature generation */
822 ret = ec_sign_finalize(&sig_ctx, sig, siglen);
823 if (ret) {
824 ret = -1;
825 printf("Error: error when signing\n");
826 goto err;
827 }
828 }
829 else{
830 /**** We do not support streaming mode ****/
831 /* Since we don't support streaming mode, we unfortunately have to
832 * use a dynamic allocation here.
833 */
834 size_t offset = 0;
835 allocated_buff = (u8*)malloc(1);
836 if(allocated_buff == NULL){
837 ret = -1;
838 printf("Error: allocation error\n");
839 goto err;
840 }
841 if((hdr_type != NULL) && (version != NULL)){
842 allocated_buff = (u8*)realloc(allocated_buff, sizeof(hdr));
843 if(allocated_buff == NULL){
844 ret = -1;
845 printf("Error: allocation error\n");
846 goto err;
847 }
848 memcpy(allocated_buff, &hdr, sizeof(hdr));
849 offset += sizeof(hdr);
850 }
851 in_file = fopen(in_fname, "rb");
852 if (in_file == NULL) {
853 ret = -1;
854 printf("Error: file %s cannot be opened\n", in_fname);
855 goto err;
856 }
857
858 eof = 0;
859 clearerr(in_file);
860 while (raw_data_len && !eof) {
861 to_read =
862 (raw_data_len <
863 sizeof(buf)) ? raw_data_len : sizeof(buf);
864 read = fread(buf, 1, to_read, in_file);
865 if (read != to_read) {
866 /* Check if this was EOF */
867 ret = feof(in_file);
868 clearerr(in_file);
869 if (ret) {
870 eof = 1;
871 }
872 }
873
874 if (read > raw_data_len) {
875 /* we read more than expected: leave! */
876 break;
877 }
878
879 raw_data_len -= read;
880
881 allocated_buff = (u8*)realloc(allocated_buff, offset + read);
882 if(allocated_buff == NULL){
883 ret = -1;
884 printf("Error: allocation error\n");
885 goto err;
886 }
887 memcpy(allocated_buff + offset, buf, read);
888 offset += read;
889 }
890
891 if (raw_data_len) {
892 ret = -1;
893 printf("Error: unable to read full file content\n");
894 goto err;
895 }
896
897 /* Sign */
898 ret = ec_sign(sig, siglen, &key_pair, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len);
899 if(ret){
900 ret = -1;
901 printf("Error: error when signing\n");
902 goto err;
903 }
904 }
905
906 /* Structured export case, forge the full structured file
907 * with HEADER || raw_binary || signature
908 */
909 if((hdr_type != NULL) && (version != NULL)){
910 /***********************************/
911 /* Store the header, the raw data of the file as well as the signature */
912 ret = store_sig(in_fname, out_fname, sig, siglen, sig_type,
913 hash_type, params.curve_name, &hdr);
914 if (ret) {
915 ret = -1;
916 printf("Error: error when storing signature to %s\n",
917 out_fname);
918 goto err;
919 }
920 }
921 else{
922 /* Store the raw binary signature in the output file */
923 size_t written;
924
925 out_file = fopen(out_fname, "wb");
926 if (out_file == NULL) {
927 ret = -1;
928 printf("Error: file %s cannot be opened\n", out_fname);
929 goto err;
930 }
931 written = fwrite(sig, 1, siglen, out_file);
932 if (written != siglen) {
933 ret = -1;
934 printf("Error: error when writing to %s\n",
935 out_fname);
936 goto err;
937 }
938 }
939
940 ret = 0;
941
942 err:
943 if(in_file != NULL){
944 if(fclose(in_file)){
945 ret = -1;
946 }
947 }
948 if(in_key_file != NULL){
949 if(fclose(in_key_file)){
950 ret = -1;
951 }
952 }
953 if(out_file != NULL){
954 if(fclose(out_file)){
955 ret = -1;
956 }
957 }
958 if(allocated_buff != NULL){
959 free(allocated_buff);
960 }
961 return ret;
962 }
963
964 /* Dump metadata header */
dump_hdr_info(const metadata_hdr * hdr)965 ATTRIBUTE_WARN_UNUSED_RET static int dump_hdr_info(const metadata_hdr * hdr)
966 {
967 int ret;
968
969 if (hdr == NULL) {
970 printf("Metadata header pointer is NULL!\n");
971 ret = -1;
972 goto err;
973 }
974
975 /* Dump the header */
976 printf("Metadata header info:\n");
977 printf(" magic = 0x%08" PRIx32 "\n", hdr->magic);
978 switch (hdr->type) {
979 case IMAGE_TYPE0:
980 printf(" type = IMAGE_TYPE0\n");
981 break;
982 case IMAGE_TYPE1:
983 printf(" type = IMAGE_TYPE1\n");
984 break;
985 case IMAGE_TYPE2:
986 printf(" type = IMAGE_TYPE2\n");
987 break;
988 case IMAGE_TYPE3:
989 printf(" type = IMAGE_TYPE3\n");
990 break;
991 default:
992 printf(" type %" PRIu32 " unknown!\n", hdr->type);
993 break;
994 }
995 printf(" version = 0x%08" PRIx32 "\n", hdr->version);
996 printf(" len = 0x%08" PRIx32 "\n", hdr->len);
997 printf(" siglen = 0x%08" PRIx32 "\n", hdr->siglen);
998 ret = 0;
999
1000 err:
1001 return ret;
1002 }
1003
1004 /*
1005 * Verify signature data from file with appended signature
1006 */
verify_bin_file(const char * ec_name,const char * ec_sig_name,const char * hash_algorithm,const char * in_fname,const char * in_key_fname,const char * in_sig_fname,const char * adata,u16 adata_len)1007 ATTRIBUTE_WARN_UNUSED_RET static int verify_bin_file(const char *ec_name, const char *ec_sig_name,
1008 const char *hash_algorithm,
1009 const char *in_fname,
1010 const char *in_key_fname, const char *in_sig_fname, const char *adata, u16 adata_len)
1011 {
1012 u8 st_sig[EC_STRUCTURED_SIG_EXPORT_SIZE(EC_MAX_SIGLEN)];
1013 u8 stored_curve_name[MAX_CURVE_NAME_LEN];
1014 u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE];
1015 struct ec_verify_context verif_ctx;
1016 ec_alg_type stored_sig_type;
1017 hash_alg_type stored_hash_type;
1018 const ec_str_params *ec_str_p;
1019 ec_alg_type sig_type;
1020 hash_alg_type hash_type;
1021 u8 sig[EC_MAX_SIGLEN];
1022 u8 siglen, st_siglen;
1023 size_t read, to_read;
1024 u8 buf[MAX_BUF_LEN];
1025 u8 pub_key_buf_len;
1026 size_t raw_data_len;
1027 ec_pub_key pub_key;
1028 FILE *in_key_file = NULL;
1029 FILE *in_sig_file = NULL;
1030 ec_params params;
1031 metadata_hdr hdr;
1032 size_t exp_len;
1033 FILE *in_file = NULL;
1034 int ret, eof, check;
1035 u8 *allocated_buff = NULL;
1036
1037 MUST_HAVE(ec_name != NULL, ret, err);
1038 MUST_HAVE(ec_sig_name != NULL, ret, err);
1039 MUST_HAVE(hash_algorithm != NULL, ret, err);
1040 MUST_HAVE(in_fname != NULL, ret, err);
1041 MUST_HAVE(in_key_fname != NULL, ret, err);
1042
1043 /************************************/
1044 /* Get parameters from pretty names */
1045 ret = string_to_params(ec_name, ec_sig_name, &sig_type, &ec_str_p,
1046 hash_algorithm, &hash_type); EG(ret, err);
1047 if(adata != NULL){
1048 /* Check if ancillary data will be used */
1049 ret = check_ancillary_data(adata, sig_type, ec_sig_name, &check); EG(ret, err);
1050 }
1051 /* Import the parameters */
1052 ret = import_params(¶ms, ec_str_p); EG(ret, err);
1053
1054 ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen);
1055 if (ret) {
1056 ret = -1;
1057 printf("Error getting effective signature length from %s\n",
1058 (const char *)(ec_str_p->name->buf));
1059 goto err;
1060 }
1061
1062 /************************************/
1063 /* Import the public key from the file */
1064 in_key_file = fopen(in_key_fname, "rb");
1065 if (in_key_file == NULL) {
1066 ret = -1;
1067 printf("Error: file %s cannot be opened\n", in_key_fname);
1068 goto err;
1069 }
1070 pub_key_buf_len =(u8)fread(pub_key_buf, 1, sizeof(pub_key_buf),
1071 in_key_file);
1072 ret = ec_structured_pub_key_import_from_buf(&pub_key, ¶ms,
1073 pub_key_buf,
1074 pub_key_buf_len, sig_type);
1075 if (ret) {
1076 ret = -1;
1077 printf("Error: error when importing public key from %s\n",
1078 in_key_fname);
1079 goto err;
1080 }
1081
1082 /* Let's first get file size */
1083 ret = get_file_size(in_fname, &raw_data_len);
1084 if (ret) {
1085 ret = -1;
1086 printf("Error: cannot retrieve file %s size\n", in_fname);
1087 goto err;
1088 }
1089 if(raw_data_len == 0){
1090 ret = -1;
1091 printf("Error: file %s seems to be empty!\n", in_fname);
1092 goto err;
1093 }
1094
1095 /* Open main file to verify ... */
1096 in_file = fopen(in_fname, "rb");
1097 if (in_file == NULL) {
1098 ret = -1;
1099 printf("Error: file %s cannot be opened\n", in_fname);
1100 goto err;
1101 }
1102
1103 /*
1104 * We are in 'structured' mode, read the header and get the information
1105 * from it
1106 */
1107 if (in_sig_fname == NULL) {
1108 /* ... and first read metadata header */
1109 read = fread(&hdr, 1, sizeof(hdr), in_file);
1110 if (read != sizeof(hdr)) {
1111 ret = -1;
1112 printf("Error: unable to read metadata header "
1113 "from file\n");
1114 goto err;
1115 }
1116
1117 /* Sanity checks on the header we get */
1118 if (hdr.magic != HDR_MAGIC) {
1119 ret = -1;
1120 printf("Error: got magic 0x%08" PRIx32 " instead of 0x%08x "
1121 "from metadata header\n", hdr.magic, (unsigned int)HDR_MAGIC);
1122 goto err;
1123 }
1124
1125 st_siglen = EC_STRUCTURED_SIG_EXPORT_SIZE(siglen);
1126 MUST_HAVE(raw_data_len > (sizeof(hdr) + st_siglen), ret, err);
1127 exp_len = raw_data_len - sizeof(hdr) - st_siglen;
1128 if (hdr.len != exp_len) {
1129 ret = -1;
1130 printf("Error: got raw size of %" PRIu32 " instead of %lu from "
1131 "metadata header\n", hdr.len,
1132 (unsigned long)exp_len);
1133 goto err;
1134 }
1135
1136 if (hdr.siglen != st_siglen) {
1137 ret = -1;
1138 printf("Error: got siglen %" PRIu32 " instead of %d from "
1139 "metadata header\n", hdr.siglen, siglen);
1140 goto err;
1141 }
1142
1143 /* Dump the header */
1144 ret = dump_hdr_info(&hdr); EG(ret, err);
1145
1146 /*
1147 * We now need to seek in file to get structured signature.
1148 * Before doing that, let's first check size is large enough.
1149 */
1150 if (raw_data_len < (sizeof(hdr) + st_siglen)) {
1151 ret = -1;
1152 goto err;
1153 }
1154
1155 ret = fseek(in_file, (long)(raw_data_len - st_siglen),
1156 SEEK_SET);
1157 if (ret) {
1158 ret = -1;
1159 printf("Error: file %s cannot be seeked\n", in_fname);
1160 goto err;
1161 }
1162 read = fread(st_sig, 1, st_siglen, in_file);
1163 if (read != st_siglen) {
1164 ret = -1;
1165 printf("Error: unable to read structure sig from "
1166 "file\n");
1167 goto err;
1168 }
1169 /* Import the signature from the structured signature buffer */
1170 ret = ec_structured_sig_import_from_buf(sig, siglen,
1171 st_sig, st_siglen,
1172 &stored_sig_type,
1173 &stored_hash_type,
1174 stored_curve_name);
1175 if (ret) {
1176 ret = -1;
1177 printf("Error: error when importing signature "
1178 "from %s\n", in_fname);
1179 goto err;
1180 }
1181 if (stored_sig_type != sig_type) {
1182 ret = -1;
1183 printf("Error: signature type imported from signature "
1184 "mismatches with %s\n", ec_sig_name);
1185 goto err;
1186 }
1187 if (stored_hash_type != hash_type) {
1188 ret = -1;
1189 printf("Error: hash algorithm type imported from "
1190 "signature mismatches with %s\n",
1191 hash_algorithm);
1192 goto err;
1193 }
1194 ret = are_str_equal((char *)stored_curve_name, (char *)params.curve_name, &check); EG(ret, err);
1195 if (!check) {
1196 ret = -1;
1197 printf("Error: curve type '%s' imported from signature "
1198 "mismatches with '%s'\n", stored_curve_name,
1199 params.curve_name);
1200 goto err;
1201 }
1202
1203 /*
1204 * Get back to the beginning of file, at the beginning of header
1205 */
1206 if (fseek(in_file, 0, SEEK_SET)) {
1207 ret = -1;
1208 printf("Error: file %s cannot be seeked\n", in_fname);
1209 goto err;
1210 }
1211 exp_len += sizeof(hdr);
1212 } else {
1213 /* Get the signature size */
1214 ret = get_file_size(in_sig_fname, &to_read);
1215 if (ret) {
1216 ret = -1;
1217 printf("Error: cannot retrieve file %s size\n",
1218 in_sig_fname);
1219 goto err;
1220 }
1221 if((to_read > EC_MAX_SIGLEN) || (to_read > 255) || (to_read == 0)){
1222 /* This is not an expected size, get out */
1223 ret = -1;
1224 printf("Error: size %d of signature in %s is > max "
1225 "signature size %d or > 255",
1226 (int)to_read, in_sig_fname, EC_MAX_SIGLEN);
1227 goto err;
1228 }
1229 siglen = (u8)to_read;
1230 /* Read the raw signature from the signature file */
1231 in_sig_file = fopen(in_sig_fname, "rb");
1232 if (in_sig_file == NULL) {
1233 ret = -1;
1234 printf("Error: file %s cannot be opened\n",
1235 in_sig_fname);
1236 goto err;
1237 }
1238 read = fread(&sig, 1, siglen, in_sig_file);
1239 if (read != siglen) {
1240 ret = -1;
1241 printf("Error: unable to read signature from %s\n",
1242 in_sig_fname);
1243 goto err;
1244 }
1245 exp_len = raw_data_len;
1246 }
1247
1248 /* Check if we support streaming */
1249 ret = is_verify_streaming_mode_supported(sig_type, &check); EG(ret, err);
1250 if(check){
1251 /**** We support streaming mode ****/
1252 /*
1253 * ... and read file content chunk by chunk to compute signature
1254 */
1255 ret = ec_verify_init(&verif_ctx, &pub_key, sig, siglen,
1256 sig_type, hash_type, (const u8*)adata, adata_len);
1257 if (ret) {
1258 ret = -1;
1259 printf("Error: error when verifying ...\n");
1260 goto err;
1261 }
1262
1263 eof = 0;
1264 clearerr(in_file);
1265 while (exp_len && !eof) {
1266 to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf);
1267 read = fread(buf, 1, to_read, in_file);
1268 if (read != to_read) {
1269 /* Check if this was EOF */
1270 ret = feof(in_file);
1271 clearerr(in_file);
1272 if (ret) {
1273 eof = 1;
1274 }
1275 }
1276
1277 if (read > exp_len) {
1278 /* we read more than expected: leave! */
1279 break;
1280 }
1281
1282 exp_len -= read;
1283
1284 ret = ec_verify_update(&verif_ctx, buf, (u32)read);
1285 if(ret){
1286 ret = -1;
1287 printf("Error: error when verifying ...\n");
1288 goto err;
1289 }
1290 }
1291 if (exp_len) {
1292 ret = -1;
1293 printf("Error: unable to read full file content\n");
1294 goto err;
1295 }
1296 ret = ec_verify_finalize(&verif_ctx);
1297 if (ret) {
1298 ret = -1;
1299 goto err;
1300 }
1301 }
1302 else{
1303 /**** We do not support streaming mode ****/
1304 /* Since we don't support streaming mode, we unfortunately have to
1305 * use a dynamic allocation here.
1306 */
1307 size_t offset = 0;
1308 allocated_buff = (u8*)malloc(1);
1309
1310 eof = 0;
1311 clearerr(in_file);
1312 while (exp_len && !eof) {
1313 to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf);
1314 read = fread(buf, 1, to_read, in_file);
1315 if (read != to_read) {
1316 /* Check if this was EOF */
1317 ret = feof(in_file);
1318 clearerr(in_file);
1319 if (ret) {
1320 eof = 1;
1321 }
1322 }
1323
1324 if (read > exp_len) {
1325 /* we read more than expected: leave! */
1326 break;
1327 }
1328
1329 exp_len -= read;
1330
1331 allocated_buff = (u8*)realloc(allocated_buff, offset + read);
1332 if(allocated_buff == NULL){
1333 ret = -1;
1334 printf("Error: allocation error\n");
1335 goto err;
1336 }
1337 memcpy(allocated_buff + offset, buf, read);
1338 offset += read;
1339 }
1340 if (exp_len) {
1341 ret = -1;
1342 printf("Error: unable to read full file content\n");
1343 goto err;
1344 }
1345
1346 ret = ec_verify(sig, siglen, &pub_key, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len);
1347 if (ret) {
1348 ret = -1;
1349 goto err;
1350 }
1351
1352 }
1353
1354 ret = 0;
1355
1356 err:
1357 if(in_file != NULL){
1358 if(fclose(in_file)){
1359 ret = -1;
1360 }
1361 }
1362 if(in_key_file != NULL){
1363 if(fclose(in_key_file)){
1364 ret = -1;
1365 }
1366 }
1367 if(in_sig_file != NULL){
1368 if(fclose(in_sig_file)){
1369 ret = -1;
1370 }
1371 }
1372 if(allocated_buff != NULL){
1373 free(allocated_buff);
1374 }
1375 return ret;
1376 }
1377
1378 /* Compute 'scalar * Point' on the provided curve and prints
1379 * the result.
1380 */
ec_scalar_mult(const char * ec_name,const char * scalar_file,const char * point_file,const char * outfile_name)1381 ATTRIBUTE_WARN_UNUSED_RET static int ec_scalar_mult(const char *ec_name,
1382 const char *scalar_file,
1383 const char *point_file,
1384 const char *outfile_name)
1385 {
1386 const ec_str_params *ec_str_p;
1387 ec_params curve_params;
1388 int ret;
1389 u8 buf[MAX_BUF_LEN];
1390 size_t buf_len;
1391 FILE *in_file = NULL;
1392 FILE *out_file = NULL;
1393 u16 coord_len;
1394
1395 /* Scalar (natural number) to import */
1396 nn d;
1397 /* Point to import */
1398 prj_pt Q;
1399 d.magic = Q.magic = WORD(0);
1400
1401 MUST_HAVE(ec_name != NULL, ret, err);
1402 MUST_HAVE(scalar_file != NULL, ret, err);
1403 MUST_HAVE(point_file != NULL, ret, err);
1404 MUST_HAVE(outfile_name != NULL, ret, err);
1405
1406 /* Get parameters from pretty names */
1407 ret = string_to_params(ec_name, NULL, NULL, &ec_str_p,
1408 NULL, NULL); EG(ret, err);
1409
1410 /* Import the parameters */
1411 ret = import_params(&curve_params, ec_str_p); EG(ret, err);
1412
1413 /* Import the scalar in the local buffer from the file */
1414 /* Let's first get file size */
1415 ret = get_file_size(scalar_file, &buf_len);
1416 if(buf_len == 0){
1417 ret = -1;
1418 printf("Error: file %s seems to be empty!\n", scalar_file);
1419 goto err;
1420 }
1421 if (ret) {
1422 ret = -1;
1423 printf("Error: cannot retrieve file %s size\n", scalar_file);
1424 goto err;
1425 }
1426 if(buf_len > sizeof(buf)){
1427 ret = -1;
1428 printf("Error: file %s content too large for our local buffers\n", scalar_file);
1429 goto err;
1430 }
1431 /* Open main file to verify ... */
1432 in_file = fopen(scalar_file, "rb");
1433 if (in_file == NULL) {
1434 ret = -1;
1435 printf("Error: file %s cannot be opened\n", scalar_file);
1436 goto err;
1437 }
1438 /* Read the content of the file */
1439 if(fread(buf, 1, buf_len, in_file) != buf_len){
1440 ret = -1;
1441 printf("Error: error when reading in %s\n", scalar_file);
1442 goto err;
1443 }
1444 /* Import the scalar */
1445 ret = nn_init_from_buf(&d, buf, (u16)buf_len); EG(ret, err);
1446
1447 /* Import the point in the local buffer from the file */
1448 /* Let's first get file size */
1449 ret = get_file_size(point_file, &buf_len);
1450 if (ret) {
1451 ret = -1;
1452 printf("Error: cannot retrieve file %s size\n", point_file);
1453 goto err;
1454 }
1455 if(buf_len > sizeof(buf)){
1456 ret = -1;
1457 printf("Error: file %s content too large for our local buffers\n", point_file);
1458 goto err;
1459 }
1460 ret = fclose(in_file); EG(ret, err);
1461 in_file = NULL;
1462 /* Open main file to verify ... */
1463 in_file = fopen(point_file, "rb");
1464 if (in_file == NULL) {
1465 ret = -1;
1466 printf("Error: file %s cannot be opened\n", point_file);
1467 goto err;
1468 }
1469 /* Read the content of the file */
1470 if(fread(buf, 1, buf_len, in_file) != buf_len){
1471 ret = -1;
1472 printf("Error: error when reading in %s\n", point_file);
1473 goto err;
1474 }
1475 /* Import the point */
1476 if(prj_pt_import_from_buf(&Q, buf, (u16)buf_len, &(curve_params.ec_curve))){
1477 ret = -1;
1478 printf("Error: error when importing the projective point from %s\n", point_file);
1479 goto err;
1480 }
1481
1482 #ifdef USE_SIG_BLINDING
1483 /* NB: we use a blind scalar multiplication here since we do not want our
1484 * private d to leak ...
1485 */
1486 ret = prj_pt_mul_blind(&Q, &d, &Q); EG(ret, err);
1487 #else
1488 ret = prj_pt_mul(&Q, &d, &Q); EG(ret, err);
1489 #endif
1490 /* Get the unique representation of the point */
1491 ret = prj_pt_unique(&Q, &Q); EG(ret, err);
1492
1493 /* Export the projective point in the local buffer */
1494 coord_len = (u16)(3 * BYTECEIL((Q.crv)->a.ctx->p_bitlen));
1495 if(coord_len > sizeof(buf)){
1496 ret = -1;
1497 printf("Error: error when exporting the point\n");
1498 goto err;
1499 }
1500 if(prj_pt_export_to_buf(&Q, buf, coord_len)){
1501 ret = -1;
1502 printf("Error: error when exporting the point\n");
1503 goto err;
1504 }
1505 /* Now save the coordinates in the output file */
1506 out_file = fopen(outfile_name, "wb");
1507 if (out_file == NULL) {
1508 ret = -1;
1509 printf("Error: file %s cannot be opened\n", outfile_name);
1510 goto err;
1511 }
1512
1513 /* Write in the file */
1514 if(fwrite(buf, 1, coord_len, out_file) != coord_len){
1515 ret = -1;
1516 printf("Error: error when writing to %s\n", outfile_name);
1517 goto err;
1518 }
1519
1520 ret = 0;
1521
1522 err:
1523 /* Uninit local variables */
1524 nn_uninit(&d);
1525 prj_pt_uninit(&Q);
1526
1527 if(in_file != NULL){
1528 if(fclose(in_file)){
1529 ret = -1;
1530 }
1531 }
1532 if(out_file != NULL){
1533 if(fclose(out_file)){
1534 ret = -1;
1535 }
1536 }
1537 return ret;
1538 }
1539
1540
print_curves(void)1541 static void print_curves(void)
1542 {
1543 u8 i;
1544
1545 /* Print all the available curves */
1546 for (i = 0; i < EC_CURVES_NUM; i++) {
1547 printf("%s ", (const char *)(ec_maps[i].params->name->buf));
1548 }
1549
1550 return;
1551 }
1552
print_hash_algs(void)1553 static void print_hash_algs(void)
1554 {
1555 int i;
1556
1557 /* Print all the available hash functions */
1558 for (i = 0; hash_maps[i].type != UNKNOWN_HASH_ALG; i++) {
1559 printf("%s ", hash_maps[i].name);
1560 }
1561
1562 return;
1563 }
1564
print_sig_algs(void)1565 static void print_sig_algs(void)
1566 {
1567 int i;
1568
1569 /* Print all the available signature schemes */
1570 for (i = 0; ec_sig_maps[i].type != UNKNOWN_ALG; i++) {
1571 printf("%s ", ec_sig_maps[i].name);
1572 }
1573
1574 return;
1575 }
1576
print_help(const char * prog_name)1577 static void print_help(const char *prog_name)
1578 {
1579 printf("%s expects at least one argument\n", prog_name ? prog_name : "NULL");
1580 printf("\targ1 = 'gen_keys', 'sign', 'verify', 'struct_sign', 'struct_verify' or 'scalar_mult'\n");
1581 }
1582
1583 #ifdef __cplusplus
1584 /* In case of a C++ compiler, preserve our "main"
1585 * linkage.
1586 */
1587 extern "C" {
1588 int main(int argc, char *argv[]);
1589 }
1590 #endif
1591
main(int argc,char * argv[])1592 int main(int argc, char *argv[])
1593 {
1594 int ret, check, found;
1595 u32 len;
1596 const char *adata = NULL;
1597 u16 adata_len = 0;
1598
1599 if (argc < 2) {
1600 ret = -1;
1601 print_help(argv[0]);
1602 goto err;
1603 }
1604
1605 found = 0;
1606 ret = are_str_equal(argv[1], "gen_keys", &check); EG(ret, err);
1607 if (check) {
1608 found = 1;
1609 /* Generate keys ---------------------------------
1610 *
1611 * arg1 = curve name ("frp256v1", ...)
1612 * arg2 = algorithm type ("ECDSA", "ECKCDSA", ...)
1613 * arg3 = file name prefix
1614 */
1615 if (argc != 5){
1616 ret = -1;
1617 printf("Bad args number for %s %s:\n", argv[0],
1618 argv[1]);
1619 printf("\targ1 = curve name: ");
1620 print_curves();
1621 printf("\n");
1622
1623 printf("\targ2 = signature algorithm type: ");
1624 print_sig_algs();
1625 printf("\n");
1626
1627 printf("\targ3 = file name prefix\n");
1628 printf("\n");
1629
1630 goto err;
1631 }
1632 if(generate_and_export_key_pair(argv[2], argv[3], argv[4])){
1633 ret = -1;
1634 printf("gen_key error ...\n");
1635 goto err;
1636 }
1637 }
1638 ret = are_str_equal(argv[1], "sign", &check); EG(ret, err);
1639 if (check) {
1640 found = 1;
1641 /* Sign something --------------------------------
1642 * Signature is structured, i.e. the output is a self contained
1643 * data image
1644 * arg1 = curve name ("frp256v1", ...)
1645 * arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)
1646 * arg3 = hash algorithm type ("SHA256", "SHA512", ...)
1647 * arg4 = input file to sign
1648 * arg5 = input file containing the private key
1649 * arg6 = output file containing the signature
1650 * arg7 (optional) = ancillary data to be used
1651 */
1652 if ((argc != 8) && (argc != 9)) {
1653 ret = -1;
1654 printf("Bad args number for %s %s:\n", argv[0],
1655 argv[1]);
1656 printf("\targ1 = curve name: ");
1657 print_curves();
1658 printf("\n");
1659
1660 printf("\targ2 = signature algorithm type: ");
1661 print_sig_algs();
1662 printf("\n");
1663
1664 printf("\targ3 = hash algorithm type: ");
1665 print_hash_algs();
1666 printf("\n");
1667
1668 printf("\targ4 = input file to sign\n");
1669 printf("\targ5 = input file containing the private key (in raw binary format)\n");
1670 printf("\targ6 = output file containing the signature\n");
1671 printf("\t<arg7 (optional) = ancillary data to be used>\n");
1672 goto err;
1673 }
1674 if(argc == 9){
1675 adata = argv[8];
1676 ret = local_strlen(adata, &len); EG(ret, err);
1677 MUST_HAVE(len <= 0xffff, ret, err);
1678 adata_len = (u16)len;
1679 }
1680 if(sign_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6],
1681 argv[7], NULL, NULL, adata, adata_len)){
1682 ret = -1;
1683 printf("sign error ...\n");
1684 goto err;
1685 }
1686 }
1687 ret = are_str_equal(argv[1], "verify", &check); EG(ret, err);
1688 if (check) {
1689 found = 1;
1690 /* Verify something ------------------------------
1691 *
1692 * arg1 = curve name ("frp256v1", ...)
1693 * arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)
1694 * arg3 = hash algorithm type ("SHA256", "SHA512", ...)
1695 * arg = input file to verify
1696 * arg5 = input file with the public key
1697 * arg6 = input file containing the signature
1698 * arg7 (optional) = ancillary data to be used
1699 */
1700 if ((argc != 8) && (argc != 9)) {
1701 ret = -1;
1702 printf("Bad args number for %s %s:\n", argv[0],
1703 argv[1]);
1704 printf("\targ1 = curve name: ");
1705 print_curves();
1706 printf("\n");
1707
1708 printf("\targ2 = signature algorithm type: ");
1709 print_sig_algs();
1710 printf("\n");
1711
1712 printf("\targ3 = hash algorithm type: ");
1713 print_hash_algs();
1714 printf("\n");
1715
1716 printf("\targ4 = input file to verify\n");
1717 printf("\targ5 = input file containing the public key (in raw binary format)\n");
1718 printf("\targ6 = input file containing the signature\n");
1719 printf("\t<arg7 (optional) = ancillary data to be used>\n");
1720 goto err;
1721 }
1722 if(argc == 9){
1723 adata = argv[8];
1724 ret = local_strlen(adata, &len); EG(ret, err);
1725 MUST_HAVE(len <= 0xffff, ret, err);
1726 adata_len = (u16)len;
1727 }
1728 if (verify_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], adata, adata_len)) {
1729 ret = -1;
1730 printf("Signature check of %s failed\n", argv[5]);
1731 goto err;
1732 } else {
1733 printf("Signature check of %s OK\n", argv[5]);
1734 }
1735 }
1736 ret = are_str_equal(argv[1], "struct_sign", &check); EG(ret, err);
1737 if (check) {
1738 found = 1;
1739 /* Sign something --------------------------------
1740 * Signature is structured, i.e. the output is a self contained
1741 * data image
1742 * arg1 = curve name ("frp256v1", ...)
1743 * arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)
1744 * arg3 = hash algorithm type ("SHA256", "SHA512", ...)
1745 * arg4 = input file to sign
1746 * arg5 = input file with the private key
1747 * arg6 = output file containing the appended signature
1748 * arg7 = metadata header type
1749 * arg8 = version of the metadata header
1750 * arg9 (optional) = ancillary data to be used
1751 */
1752 if ((argc != 10) && (argc != 11)) {
1753 ret = -1;
1754 printf("Bad args number for %s %s:\n", argv[0],
1755 argv[1]);
1756 printf("\targ1 = curve name: ");
1757 print_curves();
1758 printf("\n");
1759
1760 printf("\targ2 = signature algorithm type: ");
1761 print_sig_algs();
1762 printf("\n");
1763
1764 printf("\targ3 = hash algorithm type: ");
1765 print_hash_algs();
1766 printf("\n");
1767
1768 printf("\targ4 = input file to sign\n");
1769 printf("\targ5 = input file containing the private key (in raw binary format)\n");
1770 printf("\targ6 = output file containing the appended signature\n");
1771 printf("\targ7 = metadata header type (IMAGE_TYPE0, IMAGE_TYPE1, ...)\n");
1772 printf("\targ8 = version of the metadata header\n");
1773 printf("\t<arg9 (optional) = ancillary data to be used>\n");
1774 goto err;
1775 }
1776 if(argc == 11){
1777 adata = argv[10];
1778 ret = local_strlen(adata, &len); EG(ret, err);
1779 MUST_HAVE(len <= 0xffff, ret, err);
1780 adata_len = (u16)len;
1781 }
1782 if(sign_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6],
1783 argv[7], argv[8], argv[9], adata, adata_len)){
1784 ret = -1;
1785 printf("struct_sign error ...\n");
1786 goto err;
1787 }
1788 }
1789 ret = are_str_equal(argv[1], "struct_verify", &check); EG(ret, err);
1790 if (check) {
1791 found = 1;
1792 /* Verify something ------------------------------
1793 *
1794 * arg1 = curve name ("frp256v1", ...)
1795 * arg2 = signature algorithm type ("ECDSA", "ECKCDSA", ...)
1796 * arg3 = hash algorithm type ("SHA256", "SHA512", ...)
1797 * arg4 = input file to verify
1798 * arg5 = input file containing the public key (in raw binary format)
1799 * arg6 (optional) = ancillary data to be used
1800 */
1801 if ((argc != 7) && (argc != 8)) {
1802 ret = -1;
1803 printf("Bad args number for %s %s:\n", argv[0],
1804 argv[1]);
1805 printf("\targ1 = curve name: ");
1806 print_curves();
1807 printf("\n");
1808
1809 printf("\targ2 = signature algorithm type: ");
1810 print_sig_algs();
1811 printf("\n");
1812
1813 printf("\targ3 = hash algorithm type: ");
1814 print_hash_algs();
1815 printf("\n");
1816
1817 printf("\targ4 = input file to verify\n");
1818 printf("\targ5 = input file containing the public key (in raw binary format)\n");
1819 printf("\t<arg6 (optional) = ancillary data to be used>\n");
1820 goto err;
1821 }
1822 if(argc == 8){
1823 adata = argv[7];
1824 ret = local_strlen(adata, &len); EG(ret, err);
1825 MUST_HAVE(len <= 0xffff, ret, err);
1826 adata_len = (u16)len;
1827 }
1828 if (verify_bin_file(argv[2], argv[3], argv[4], argv[5], argv[6], NULL, adata, adata_len)) {
1829 ret = -1;
1830 printf("Signature check of %s failed\n", argv[5]);
1831 goto err;
1832 } else {
1833 printf("Signature check of %s OK\n", argv[5]);
1834 }
1835 }
1836 ret = are_str_equal(argv[1], "scalar_mult", &check); EG(ret, err);
1837 if (check) {
1838 found = 1;
1839 /* Point scalar multiplication --------------------
1840 *
1841 * arg1 = curve name ("frp256v1", ...)
1842 * arg2 = scalar
1843 * arg3 = point to multiply
1844 * arg4 = file name where to save the result
1845 */
1846 if (argc != 6) {
1847 ret = -1;
1848 printf("Bad args number for %s %s:\n", argv[0],
1849 argv[1]);
1850 printf("\targ1 = curve name: ");
1851 print_curves();
1852 printf("\n");
1853
1854 printf("\targ2 = scalar bin file\n");
1855 printf("\targ3 = point to multiply bin file (projective coordinates)\n");
1856 printf("\targ4 = file name where to save the result\n");
1857 goto err;
1858 }
1859 if(ec_scalar_mult(argv[2], argv[3], argv[4], argv[5])){
1860 ret = -1;
1861 printf("Scalar multiplication failed\n");
1862 goto err;
1863 }
1864 }
1865
1866 if (found == 0) {
1867 /* Bad first argument, print help */
1868 ret = -1;
1869 printf("Bad first argument '%s'\n", argv[1]);
1870 print_help(argv[0]);
1871 goto err;
1872 }
1873
1874 ret = 0;
1875
1876 err:
1877 return ret;
1878 }
1879