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(¶ms, ec_str_p); EG(ret, err); 260 261 /* Generate the key pair */ 262 ret = ec_key_pair_gen(&kp, ¶ms, sig_type); EG(ret, err); 263 264 /* Get the unique affine equivalent representation of the projective point for the public key. 265 * This avoids ambiguity when exporting the point, and is mostly here 266 * for compatibility with external libraries. 267 */ 268 ret = prj_pt_unique(&(kp.pub_key.y), &(kp.pub_key.y)); EG(ret, err); 269 270 /*************************/ 271 272 /* Export the private key to the raw binary file */ 273 ret = local_strnlen(fname_prefix, fname_len, &len); EG(ret, err); 274 MUST_HAVE(len <= 0xffff, ret, err); 275 prefix_len = (u16)len; 276 ret = local_memset(fname, 0, fname_len); EG(ret, err); 277 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err); 278 ret = local_strncat(fname, "_private_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err); 279 file = fopen(fname, "wb"); 280 if (file == NULL) { 281 ret = -1; 282 printf("Error: file %s cannot be opened\n", fname); 283 goto err; 284 } 285 286 ret = export_private_key(file, NULL, &(kp.priv_key), RAWBIN); 287 if (ret) { 288 ret = -1; 289 printf("Error exporting the private key\n"); 290 goto err; 291 } 292 ret = fclose(file); EG(ret, err); 293 file = NULL; 294 295 /* Export the private key to the .h file */ 296 ret = local_memset(fname, 0, fname_len); EG(ret, err); 297 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err); 298 ret = local_strncat(fname, "_private_key.h", (u32)(fname_len - prefix_len)); EG(ret, err); 299 file = fopen(fname, "w"); 300 if (file == NULL) { 301 ret = -1; 302 printf("Error: file %s cannot be opened\n", fname); 303 goto err; 304 } 305 306 snprintf(kname, kname_len, "%s_%s_private_key", ec_name, ec_sig_name); 307 ret = export_private_key(file, kname, &(kp.priv_key), DOTH); 308 if (ret) { 309 ret = -1; 310 printf("Error: error exporting the private key\n"); 311 goto err; 312 } 313 ret = fclose(file); EG(ret, err); 314 file = NULL; 315 316 /*************************/ 317 318 /* Export the public key to the raw binary file */ 319 ret = local_memset(fname, 0, fname_len); EG(ret, err); 320 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err); 321 ret = local_strncat(fname, "_public_key.bin", (u32)(fname_len - prefix_len)); EG(ret, err); 322 file = fopen(fname, "wb"); 323 if (file == NULL) { 324 ret = -1; 325 printf("Error: file %s cannot be opened\n", fname); 326 goto err; 327 } 328 ret = export_public_key(file, NULL, &(kp.pub_key), RAWBIN); 329 if (ret) { 330 ret = -1; 331 printf("Error exporting the public key\n"); 332 goto err; 333 } 334 ret = fclose(file); EG(ret, err); 335 file = NULL; 336 337 /* Export the public key to the .h file */ 338 ret = local_memset(fname, 0, fname_len); EG(ret, err); 339 ret = local_memcpy(fname, fname_prefix, prefix_len); EG(ret, err); 340 ret = local_strncat(fname, "_public_key.h", (u32)(fname_len - prefix_len)); EG(ret, err); 341 file = fopen(fname, "w"); 342 if (file == NULL) { 343 ret = -1; 344 printf("Error: file %s cannot be opened\n", fname); 345 goto err; 346 } 347 348 snprintf(kname, kname_len, "%s_%s_public_key", ec_name, ec_sig_name); 349 ret = export_public_key(file, kname, &(kp.pub_key), DOTH); 350 if (ret) { 351 ret = -1; 352 printf("Error exporting the public key\n"); 353 goto err; 354 } 355 ret = fclose(file); EG(ret, err); 356 file = NULL; 357 358 ret = 0; 359 360 err: 361 if(file != NULL){ 362 if(fclose(file)){ 363 ret = -1; 364 } 365 } 366 return ret; 367 } 368 369 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(¶ms, ec_str_p); EG(ret, err); 693 694 /************************************/ 695 /* Import the private key from the file */ 696 in_key_file = fopen(in_key_fname, "rb"); 697 if (in_key_file == NULL) { 698 ret = -1; 699 printf("Error: file %s cannot be opened\n", in_key_fname); 700 goto err; 701 } 702 priv_key_buf_len = (u8)fread(priv_key_buf, 1, sizeof(priv_key_buf), 703 in_key_file); 704 ret = ec_structured_key_pair_import_from_priv_key_buf(&key_pair, 705 ¶ms, 706 priv_key_buf, 707 priv_key_buf_len, 708 sig_type); 709 if (ret) { 710 ret = -1; 711 printf("Error: error when importing key pair from %s\n", 712 in_key_fname); 713 goto err; 714 } 715 716 ret = get_file_size(in_fname, &raw_data_len); 717 if (ret) { 718 ret = -1; 719 printf("Error: cannot retrieve file %s size\n", in_fname); 720 goto err; 721 } 722 if(raw_data_len == 0){ 723 ret = -1; 724 printf("Error: file %s seems to be empty!\n", in_fname); 725 goto err; 726 } 727 ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen); 728 if (ret) { 729 ret = -1; 730 printf("Error getting effective signature length from %s\n", 731 (const char *)(ec_str_p->name->buf)); 732 goto err; 733 } 734 735 /* Structured export case, we forge a header */ 736 if((hdr_type != NULL) && (version != NULL)){ 737 /************************************/ 738 /* Forge the header */ 739 ret = generate_metadata_hdr(&hdr, hdr_type, version, raw_data_len, 740 EC_STRUCTURED_SIG_EXPORT_SIZE(siglen)); 741 742 if (ret) { 743 ret = -1; 744 printf("Error: error when generating metadata\n"); 745 goto err; 746 } 747 } 748 749 /* Check if we support streaming */ 750 ret = is_sign_streaming_mode_supported(sig_type, &check); EG(ret, err); 751 if(check){ 752 /**** We support streaming mode ****/ 753 /* 754 * Initialize signature context and start signature computation 755 * with generated metadata header. 756 */ 757 ret = ec_sign_init(&sig_ctx, &key_pair, sig_type, hash_type, (const u8*)adata, adata_len); 758 if (ret) { 759 ret = -1; 760 printf("Error: error when signing\n"); 761 goto err; 762 } 763 764 /* Structured export case, we prepend the header in the signature */ 765 if((hdr_type != NULL) && (version != NULL)){ 766 ret = ec_sign_update(&sig_ctx, (const u8 *)&hdr, sizeof(metadata_hdr)); 767 if (ret) { 768 ret = -1; 769 printf("Error: error when signing\n"); 770 goto err; 771 } 772 } 773 774 /* 775 * Read file content chunk by chunk up to file length, passing each 776 * chunk to signature update function 777 */ 778 in_file = fopen(in_fname, "rb"); 779 if (in_file == NULL) { 780 ret = -1; 781 printf("Error: file %s cannot be opened\n", in_fname); 782 goto err; 783 } 784 785 eof = 0; 786 clearerr(in_file); 787 while (raw_data_len && !eof) { 788 to_read = 789 (raw_data_len < 790 sizeof(buf)) ? raw_data_len : sizeof(buf); 791 memset(buf, 0, sizeof(buf)); 792 read = fread(buf, 1, to_read, in_file); 793 if (read != to_read) { 794 /* Check if this was EOF */ 795 ret = feof(in_file); 796 clearerr(in_file); 797 if (ret) { 798 eof = 1; 799 } 800 } 801 802 if (read > raw_data_len) { 803 /* we read more than expected: leave! */ 804 break; 805 } 806 807 raw_data_len -= read; 808 809 ret = ec_sign_update(&sig_ctx, buf, (u32)read); 810 if (ret) { 811 break; 812 } 813 } 814 815 if (raw_data_len) { 816 ret = -1; 817 printf("Error: unable to read full file content\n"); 818 goto err; 819 } 820 821 /* We can now complete signature generation */ 822 ret = ec_sign_finalize(&sig_ctx, sig, siglen); 823 if (ret) { 824 ret = -1; 825 printf("Error: error when signing\n"); 826 goto err; 827 } 828 } 829 else{ 830 /**** We do not support streaming mode ****/ 831 /* Since we don't support streaming mode, we unfortunately have to 832 * use a dynamic allocation here. 833 */ 834 size_t offset = 0; 835 allocated_buff = (u8*)malloc(1); 836 if(allocated_buff == NULL){ 837 ret = -1; 838 printf("Error: allocation error\n"); 839 goto err; 840 } 841 if((hdr_type != NULL) && (version != NULL)){ 842 allocated_buff = (u8*)realloc(allocated_buff, sizeof(hdr)); 843 if(allocated_buff == NULL){ 844 ret = -1; 845 printf("Error: allocation error\n"); 846 goto err; 847 } 848 memcpy(allocated_buff, &hdr, sizeof(hdr)); 849 offset += sizeof(hdr); 850 } 851 in_file = fopen(in_fname, "rb"); 852 if (in_file == NULL) { 853 ret = -1; 854 printf("Error: file %s cannot be opened\n", in_fname); 855 goto err; 856 } 857 858 eof = 0; 859 clearerr(in_file); 860 while (raw_data_len && !eof) { 861 to_read = 862 (raw_data_len < 863 sizeof(buf)) ? raw_data_len : sizeof(buf); 864 read = fread(buf, 1, to_read, in_file); 865 if (read != to_read) { 866 /* Check if this was EOF */ 867 ret = feof(in_file); 868 clearerr(in_file); 869 if (ret) { 870 eof = 1; 871 } 872 } 873 874 if (read > raw_data_len) { 875 /* we read more than expected: leave! */ 876 break; 877 } 878 879 raw_data_len -= read; 880 881 allocated_buff = (u8*)realloc(allocated_buff, offset + read); 882 if(allocated_buff == NULL){ 883 ret = -1; 884 printf("Error: allocation error\n"); 885 goto err; 886 } 887 memcpy(allocated_buff + offset, buf, read); 888 offset += read; 889 } 890 891 if (raw_data_len) { 892 ret = -1; 893 printf("Error: unable to read full file content\n"); 894 goto err; 895 } 896 897 /* Sign */ 898 ret = ec_sign(sig, siglen, &key_pair, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len); 899 if(ret){ 900 ret = -1; 901 printf("Error: error when signing\n"); 902 goto err; 903 } 904 } 905 906 /* Structured export case, forge the full structured file 907 * with HEADER || raw_binary || signature 908 */ 909 if((hdr_type != NULL) && (version != NULL)){ 910 /***********************************/ 911 /* Store the header, the raw data of the file as well as the signature */ 912 ret = store_sig(in_fname, out_fname, sig, siglen, sig_type, 913 hash_type, params.curve_name, &hdr); 914 if (ret) { 915 ret = -1; 916 printf("Error: error when storing signature to %s\n", 917 out_fname); 918 goto err; 919 } 920 } 921 else{ 922 /* Store the raw binary signature in the output file */ 923 size_t written; 924 925 out_file = fopen(out_fname, "wb"); 926 if (out_file == NULL) { 927 ret = -1; 928 printf("Error: file %s cannot be opened\n", out_fname); 929 goto err; 930 } 931 written = fwrite(sig, 1, siglen, out_file); 932 if (written != siglen) { 933 ret = -1; 934 printf("Error: error when writing to %s\n", 935 out_fname); 936 goto err; 937 } 938 } 939 940 ret = 0; 941 942 err: 943 if(in_file != NULL){ 944 if(fclose(in_file)){ 945 ret = -1; 946 } 947 } 948 if(in_key_file != NULL){ 949 if(fclose(in_key_file)){ 950 ret = -1; 951 } 952 } 953 if(out_file != NULL){ 954 if(fclose(out_file)){ 955 ret = -1; 956 } 957 } 958 if(allocated_buff != NULL){ 959 free(allocated_buff); 960 } 961 return ret; 962 } 963 964 /* Dump metadata header */ 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(¶ms, ec_str_p); EG(ret, err); 1053 1054 ret = ec_get_sig_len(¶ms, sig_type, hash_type, &siglen); 1055 if (ret) { 1056 ret = -1; 1057 printf("Error getting effective signature length from %s\n", 1058 (const char *)(ec_str_p->name->buf)); 1059 goto err; 1060 } 1061 1062 /************************************/ 1063 /* Import the public key from the file */ 1064 in_key_file = fopen(in_key_fname, "rb"); 1065 if (in_key_file == NULL) { 1066 ret = -1; 1067 printf("Error: file %s cannot be opened\n", in_key_fname); 1068 goto err; 1069 } 1070 pub_key_buf_len =(u8)fread(pub_key_buf, 1, sizeof(pub_key_buf), 1071 in_key_file); 1072 ret = ec_structured_pub_key_import_from_buf(&pub_key, ¶ms, 1073 pub_key_buf, 1074 pub_key_buf_len, sig_type); 1075 if (ret) { 1076 ret = -1; 1077 printf("Error: error when importing public key from %s\n", 1078 in_key_fname); 1079 goto err; 1080 } 1081 1082 /* Let's first get file size */ 1083 ret = get_file_size(in_fname, &raw_data_len); 1084 if (ret) { 1085 ret = -1; 1086 printf("Error: cannot retrieve file %s size\n", in_fname); 1087 goto err; 1088 } 1089 if(raw_data_len == 0){ 1090 ret = -1; 1091 printf("Error: file %s seems to be empty!\n", in_fname); 1092 goto err; 1093 } 1094 1095 /* Open main file to verify ... */ 1096 in_file = fopen(in_fname, "rb"); 1097 if (in_file == NULL) { 1098 ret = -1; 1099 printf("Error: file %s cannot be opened\n", in_fname); 1100 goto err; 1101 } 1102 1103 /* 1104 * We are in 'structured' mode, read the header and get the information 1105 * from it 1106 */ 1107 if (in_sig_fname == NULL) { 1108 /* ... and first read metadata header */ 1109 read = fread(&hdr, 1, sizeof(hdr), in_file); 1110 if (read != sizeof(hdr)) { 1111 ret = -1; 1112 printf("Error: unable to read metadata header " 1113 "from file\n"); 1114 goto err; 1115 } 1116 1117 /* Sanity checks on the header we get */ 1118 if (hdr.magic != HDR_MAGIC) { 1119 ret = -1; 1120 printf("Error: got magic 0x%08" PRIx32 " instead of 0x%08x " 1121 "from metadata header\n", hdr.magic, (unsigned int)HDR_MAGIC); 1122 goto err; 1123 } 1124 1125 st_siglen = EC_STRUCTURED_SIG_EXPORT_SIZE(siglen); 1126 MUST_HAVE(raw_data_len > (sizeof(hdr) + st_siglen), ret, err); 1127 exp_len = raw_data_len - sizeof(hdr) - st_siglen; 1128 if (hdr.len != exp_len) { 1129 ret = -1; 1130 printf("Error: got raw size of %" PRIu32 " instead of %lu from " 1131 "metadata header\n", hdr.len, 1132 (unsigned long)exp_len); 1133 goto err; 1134 } 1135 1136 if (hdr.siglen != st_siglen) { 1137 ret = -1; 1138 printf("Error: got siglen %" PRIu32 " instead of %d from " 1139 "metadata header\n", hdr.siglen, siglen); 1140 goto err; 1141 } 1142 1143 /* Dump the header */ 1144 ret = dump_hdr_info(&hdr); EG(ret, err); 1145 1146 /* 1147 * We now need to seek in file to get structured signature. 1148 * Before doing that, let's first check size is large enough. 1149 */ 1150 if (raw_data_len < (sizeof(hdr) + st_siglen)) { 1151 ret = -1; 1152 goto err; 1153 } 1154 1155 ret = fseek(in_file, (long)(raw_data_len - st_siglen), 1156 SEEK_SET); 1157 if (ret) { 1158 ret = -1; 1159 printf("Error: file %s cannot be seeked\n", in_fname); 1160 goto err; 1161 } 1162 read = fread(st_sig, 1, st_siglen, in_file); 1163 if (read != st_siglen) { 1164 ret = -1; 1165 printf("Error: unable to read structure sig from " 1166 "file\n"); 1167 goto err; 1168 } 1169 /* Import the signature from the structured signature buffer */ 1170 ret = ec_structured_sig_import_from_buf(sig, siglen, 1171 st_sig, st_siglen, 1172 &stored_sig_type, 1173 &stored_hash_type, 1174 stored_curve_name); 1175 if (ret) { 1176 ret = -1; 1177 printf("Error: error when importing signature " 1178 "from %s\n", in_fname); 1179 goto err; 1180 } 1181 if (stored_sig_type != sig_type) { 1182 ret = -1; 1183 printf("Error: signature type imported from signature " 1184 "mismatches with %s\n", ec_sig_name); 1185 goto err; 1186 } 1187 if (stored_hash_type != hash_type) { 1188 ret = -1; 1189 printf("Error: hash algorithm type imported from " 1190 "signature mismatches with %s\n", 1191 hash_algorithm); 1192 goto err; 1193 } 1194 ret = are_str_equal((char *)stored_curve_name, (char *)params.curve_name, &check); EG(ret, err); 1195 if (!check) { 1196 ret = -1; 1197 printf("Error: curve type '%s' imported from signature " 1198 "mismatches with '%s'\n", stored_curve_name, 1199 params.curve_name); 1200 goto err; 1201 } 1202 1203 /* 1204 * Get back to the beginning of file, at the beginning of header 1205 */ 1206 if (fseek(in_file, 0, SEEK_SET)) { 1207 ret = -1; 1208 printf("Error: file %s cannot be seeked\n", in_fname); 1209 goto err; 1210 } 1211 exp_len += sizeof(hdr); 1212 } else { 1213 /* Get the signature size */ 1214 ret = get_file_size(in_sig_fname, &to_read); 1215 if (ret) { 1216 ret = -1; 1217 printf("Error: cannot retrieve file %s size\n", 1218 in_sig_fname); 1219 goto err; 1220 } 1221 if((to_read > EC_MAX_SIGLEN) || (to_read > 255) || (to_read == 0)){ 1222 /* This is not an expected size, get out */ 1223 ret = -1; 1224 printf("Error: size %d of signature in %s is > max " 1225 "signature size %d or > 255", 1226 (int)to_read, in_sig_fname, EC_MAX_SIGLEN); 1227 goto err; 1228 } 1229 siglen = (u8)to_read; 1230 /* Read the raw signature from the signature file */ 1231 in_sig_file = fopen(in_sig_fname, "rb"); 1232 if (in_sig_file == NULL) { 1233 ret = -1; 1234 printf("Error: file %s cannot be opened\n", 1235 in_sig_fname); 1236 goto err; 1237 } 1238 read = fread(&sig, 1, siglen, in_sig_file); 1239 if (read != siglen) { 1240 ret = -1; 1241 printf("Error: unable to read signature from %s\n", 1242 in_sig_fname); 1243 goto err; 1244 } 1245 exp_len = raw_data_len; 1246 } 1247 1248 /* Check if we support streaming */ 1249 ret = is_verify_streaming_mode_supported(sig_type, &check); EG(ret, err); 1250 if(check){ 1251 /**** We support streaming mode ****/ 1252 /* 1253 * ... and read file content chunk by chunk to compute signature 1254 */ 1255 ret = ec_verify_init(&verif_ctx, &pub_key, sig, siglen, 1256 sig_type, hash_type, (const u8*)adata, adata_len); 1257 if (ret) { 1258 ret = -1; 1259 printf("Error: error when verifying ...\n"); 1260 goto err; 1261 } 1262 1263 eof = 0; 1264 clearerr(in_file); 1265 while (exp_len && !eof) { 1266 to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf); 1267 read = fread(buf, 1, to_read, in_file); 1268 if (read != to_read) { 1269 /* Check if this was EOF */ 1270 ret = feof(in_file); 1271 clearerr(in_file); 1272 if (ret) { 1273 eof = 1; 1274 } 1275 } 1276 1277 if (read > exp_len) { 1278 /* we read more than expected: leave! */ 1279 break; 1280 } 1281 1282 exp_len -= read; 1283 1284 ret = ec_verify_update(&verif_ctx, buf, (u32)read); 1285 if(ret){ 1286 ret = -1; 1287 printf("Error: error when verifying ...\n"); 1288 goto err; 1289 } 1290 } 1291 if (exp_len) { 1292 ret = -1; 1293 printf("Error: unable to read full file content\n"); 1294 goto err; 1295 } 1296 ret = ec_verify_finalize(&verif_ctx); 1297 if (ret) { 1298 ret = -1; 1299 goto err; 1300 } 1301 } 1302 else{ 1303 /**** We do not support streaming mode ****/ 1304 /* Since we don't support streaming mode, we unfortunately have to 1305 * use a dynamic allocation here. 1306 */ 1307 size_t offset = 0; 1308 allocated_buff = (u8*)malloc(1); 1309 1310 eof = 0; 1311 clearerr(in_file); 1312 while (exp_len && !eof) { 1313 to_read = (exp_len < sizeof(buf)) ? exp_len : sizeof(buf); 1314 read = fread(buf, 1, to_read, in_file); 1315 if (read != to_read) { 1316 /* Check if this was EOF */ 1317 ret = feof(in_file); 1318 clearerr(in_file); 1319 if (ret) { 1320 eof = 1; 1321 } 1322 } 1323 1324 if (read > exp_len) { 1325 /* we read more than expected: leave! */ 1326 break; 1327 } 1328 1329 exp_len -= read; 1330 1331 allocated_buff = (u8*)realloc(allocated_buff, offset + read); 1332 if(allocated_buff == NULL){ 1333 ret = -1; 1334 printf("Error: allocation error\n"); 1335 goto err; 1336 } 1337 memcpy(allocated_buff + offset, buf, read); 1338 offset += read; 1339 } 1340 if (exp_len) { 1341 ret = -1; 1342 printf("Error: unable to read full file content\n"); 1343 goto err; 1344 } 1345 1346 ret = ec_verify(sig, siglen, &pub_key, allocated_buff, (u32)offset, sig_type, hash_type, (const u8*)adata, adata_len); 1347 if (ret) { 1348 ret = -1; 1349 goto err; 1350 } 1351 1352 } 1353 1354 ret = 0; 1355 1356 err: 1357 if(in_file != NULL){ 1358 if(fclose(in_file)){ 1359 ret = -1; 1360 } 1361 } 1362 if(in_key_file != NULL){ 1363 if(fclose(in_key_file)){ 1364 ret = -1; 1365 } 1366 } 1367 if(in_sig_file != NULL){ 1368 if(fclose(in_sig_file)){ 1369 ret = -1; 1370 } 1371 } 1372 if(allocated_buff != NULL){ 1373 free(allocated_buff); 1374 } 1375 return ret; 1376 } 1377 1378 /* Compute 'scalar * Point' on the provided curve and prints 1379 * the result. 1380 */ 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 } 1879