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