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