xref: /freebsd/crypto/libecc/src/tests/ec_utils.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
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(&params, ec_str_p); EG(ret, err);
260 
261 	/* Generate the key pair */
262 	ret = ec_key_pair_gen(&kp, &params, 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(&params, 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 							      &params,
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(&params, 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(&params, ec_str_p); EG(ret, err);
1053 
1054 	ret = ec_get_sig_len(&params, 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, &params,
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