test_helper_rsa.c (31371B)
1 /* 2 This file is part of TALER 3 (C) 2020, 2021, 2022 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file util/test_helper_rsa.c 18 * @brief Tests for RSA crypto helper 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include "taler/taler_util.h" 23 24 /** 25 * Configuration has 1 minute duration and 5 minutes lookahead, but 26 * we do not get 'revocations' for expired keys. So this must be 27 * large enough to deal with key rotation during the runtime of 28 * the benchmark. 29 */ 30 #define MAX_KEYS 1024 31 32 /** 33 * How many random key revocations should we test? 34 */ 35 #define NUM_REVOKES 3 36 37 /** 38 * How many iterations of the successful signing test should we run? 39 */ 40 #define NUM_SIGN_TESTS 5 41 42 /** 43 * How many iterations of the successful signing test should we run 44 * during the benchmark phase? 45 */ 46 #define NUM_SIGN_PERFS 100 47 48 /** 49 * How many parallel clients should we use for the parallel 50 * benchmark? (> 500 may cause problems with the max open FD number limit). 51 */ 52 #define NUM_CORES 8 53 54 /** 55 * Number of keys currently in #keys. 56 */ 57 static unsigned int num_keys; 58 59 /** 60 * Keys currently managed by the helper. 61 */ 62 struct KeyData 63 { 64 /** 65 * Validity start point. 66 */ 67 struct GNUNET_TIME_Timestamp start_time; 68 69 /** 70 * Key expires for signing at @e start_time plus this value. 71 */ 72 struct GNUNET_TIME_Relative validity_duration; 73 74 /** 75 * Hash of the public key. 76 */ 77 struct TALER_RsaPubHashP h_rsa; 78 79 /** 80 * Full public key. 81 */ 82 struct TALER_DenominationPublicKey denom_pub; 83 84 /** 85 * Is this key currently valid? 86 */ 87 bool valid; 88 89 /** 90 * Did the test driver revoke this key? 91 */ 92 bool revoked; 93 }; 94 95 /** 96 * Array of all the keys we got from the helper. 97 */ 98 static struct KeyData keys[MAX_KEYS]; 99 100 101 /** 102 * Release memory occupied by #keys. 103 */ 104 static void 105 free_keys (void) 106 { 107 for (unsigned int i = 0; i<MAX_KEYS; i++) 108 if (keys[i].valid) 109 { 110 TALER_denom_pub_free (&keys[i].denom_pub); 111 keys[i].valid = false; 112 GNUNET_assert (num_keys > 0); 113 num_keys--; 114 } 115 } 116 117 118 /** 119 * Function called with information about available keys for signing. Usually 120 * only called once per key upon connect. Also called again in case a key is 121 * being revoked, in that case with an @a end_time of zero. Stores the keys 122 * status in #keys. 123 * 124 * @param cls closure, NULL 125 * @param section_name name of the denomination type in the configuration; 126 * NULL if the key has been revoked or purged 127 * @param start_time when does the key become available for signing; 128 * zero if the key has been revoked or purged 129 * @param validity_duration how long does the key remain available for signing; 130 * zero if the key has been revoked or purged 131 * @param h_rsa hash of the @a denom_pub that is available (or was purged) 132 * @param bs_pub the public key itself, NULL if the key was revoked or purged 133 * @param sm_pub public key of the security module, NULL if the key was revoked or purged 134 * @param sm_sig signature from the security module, NULL if the key was revoked or purged 135 * The signature was already verified against @a sm_pub. 136 */ 137 static void 138 key_cb (void *cls, 139 const char *section_name, 140 struct GNUNET_TIME_Timestamp start_time, 141 struct GNUNET_TIME_Relative validity_duration, 142 const struct TALER_RsaPubHashP *h_rsa, 143 struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub, 144 const struct TALER_SecurityModulePublicKeyP *sm_pub, 145 const struct TALER_SecurityModuleSignatureP *sm_sig) 146 { 147 (void) cls; 148 (void) sm_pub; 149 (void) sm_sig; 150 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 151 "Key notification about key %s in `%s'\n", 152 GNUNET_h2s (&h_rsa->hash), 153 section_name); 154 if (0 == validity_duration.rel_value_us) 155 { 156 bool found = false; 157 158 GNUNET_break (NULL == bs_pub); 159 GNUNET_break (NULL == section_name); 160 for (unsigned int i = 0; i<MAX_KEYS; i++) 161 if (0 == GNUNET_memcmp (h_rsa, 162 &keys[i].h_rsa)) 163 { 164 keys[i].valid = false; 165 keys[i].revoked = false; 166 TALER_denom_pub_free (&keys[i].denom_pub); 167 GNUNET_assert (num_keys > 0); 168 num_keys--; 169 found = true; 170 break; 171 } 172 if (! found) 173 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 174 "Error: helper announced expiration of unknown key!\n"); 175 176 return; 177 } 178 179 GNUNET_break (NULL != bs_pub); 180 for (unsigned int i = 0; i<MAX_KEYS; i++) 181 if (! keys[i].valid) 182 { 183 keys[i].valid = true; 184 keys[i].h_rsa = *h_rsa; 185 keys[i].start_time = start_time; 186 keys[i].validity_duration = validity_duration; 187 keys[i].denom_pub.bsign_pub_key 188 = GNUNET_CRYPTO_bsign_pub_incref (bs_pub); 189 num_keys++; 190 return; 191 } 192 /* too many keys! */ 193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 194 "Error: received %d live keys from the service!\n", 195 MAX_KEYS + 1); 196 } 197 198 199 /** 200 * Test key revocation logic. 201 * 202 * @param dh handle to the helper 203 * @return 0 on success 204 */ 205 static int 206 test_revocation (struct TALER_CRYPTO_RsaDenominationHelper *dh) 207 { 208 struct timespec req = { 209 .tv_nsec = 250000000 210 }; 211 212 for (unsigned int i = 0; i<NUM_REVOKES; i++) 213 { 214 uint32_t off; 215 216 off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 217 num_keys); 218 /* find index of key to revoke */ 219 for (unsigned int j = 0; j < MAX_KEYS; j++) 220 { 221 if (! keys[j].valid) 222 continue; 223 if (0 != off) 224 { 225 off--; 226 continue; 227 } 228 keys[j].revoked = true; 229 fprintf (stderr, 230 "Revoking key %s ...", 231 GNUNET_h2s (&keys[j].h_rsa.hash)); 232 TALER_CRYPTO_helper_rsa_revoke (dh, 233 &keys[j].h_rsa); 234 for (unsigned int k = 0; k<1000; k++) 235 { 236 TALER_CRYPTO_helper_rsa_poll (dh); 237 if (! keys[j].revoked) 238 break; 239 nanosleep (&req, NULL); 240 fprintf (stderr, "."); 241 } 242 if (keys[j].revoked) 243 { 244 fprintf (stderr, 245 "\nFAILED: timeout trying to revoke key %u\n", 246 j); 247 TALER_CRYPTO_helper_rsa_disconnect (dh); 248 return 2; 249 } 250 fprintf (stderr, "\n"); 251 break; 252 } 253 } 254 return 0; 255 } 256 257 258 /** 259 * Test signing logic. 260 * 261 * @param dh handle to the helper 262 * @return 0 on success 263 */ 264 static int 265 test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh) 266 { 267 struct TALER_BlindedDenominationSignature ds; 268 enum TALER_ErrorCode ec; 269 bool success = false; 270 struct TALER_PlanchetMasterSecretP ps; 271 const struct TALER_ExchangeBlindingValues *alg_values 272 = TALER_denom_ewv_rsa_singleton (); 273 struct TALER_AgeCommitmentHashP ach; 274 struct TALER_CoinPubHashP c_hash; 275 struct TALER_CoinSpendPrivateKeyP coin_priv; 276 union GNUNET_CRYPTO_BlindingSecretP bks; 277 278 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, 279 &ps, 280 sizeof (ps)); 281 TALER_planchet_setup_coin_priv (&ps, 282 alg_values, 283 &coin_priv); 284 TALER_planchet_blinding_secret_create (&ps, 285 alg_values, 286 &bks); 287 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 288 &ach, 289 sizeof(ach)); 290 291 for (unsigned int i = 0; i<MAX_KEYS; i++) 292 { 293 if (! keys[i].valid) 294 continue; 295 if (GNUNET_CRYPTO_BSA_RSA != 296 keys[i].denom_pub.bsign_pub_key->cipher) 297 continue; 298 { 299 struct TALER_PlanchetDetail pd; 300 301 GNUNET_assert (GNUNET_YES == 302 TALER_planchet_prepare (&keys[i].denom_pub, 303 alg_values, 304 &bks, 305 NULL, 306 &coin_priv, 307 &ach, 308 &c_hash, 309 &pd)); 310 { 311 struct TALER_CRYPTO_RsaSignRequest rsr = { 312 .h_rsa = &keys[i].h_rsa, 313 .msg = 314 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 315 blinded_msg, 316 .msg_size = 317 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 318 blinded_msg_size 319 }; 320 321 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 322 "Requesting signature over %u bytes with key %s\n", 323 (unsigned int) rsr.msg_size, 324 GNUNET_h2s (&rsr.h_rsa->hash)); 325 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 326 1, 327 &rsr, 328 &ds); 329 } 330 TALER_blinded_planchet_free (&pd.blinded_planchet); 331 } 332 switch (ec) 333 { 334 case TALER_EC_NONE: 335 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 336 keys[i].start_time.abs_time), 337 >, 338 GNUNET_TIME_UNIT_SECONDS)) 339 { 340 /* key worked too early */ 341 GNUNET_break (0); 342 return 4; 343 } 344 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 345 keys[i].start_time.abs_time), 346 >, 347 keys[i].validity_duration)) 348 { 349 /* key worked too later */ 350 GNUNET_break (0); 351 return 5; 352 } 353 { 354 struct TALER_DenominationSignature rs; 355 356 if (GNUNET_OK != 357 TALER_denom_sig_unblind (&rs, 358 &ds, 359 &bks, 360 &c_hash, 361 alg_values, 362 &keys[i].denom_pub)) 363 { 364 GNUNET_break (0); 365 return 6; 366 } 367 TALER_blinded_denom_sig_free (&ds); 368 if (GNUNET_OK != 369 TALER_denom_pub_verify (&keys[i].denom_pub, 370 &rs, 371 &c_hash)) 372 { 373 /* signature invalid */ 374 GNUNET_break (0); 375 TALER_denom_sig_free (&rs); 376 return 7; 377 } 378 TALER_denom_sig_free (&rs); 379 } 380 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 381 "Received valid signature for key %s\n", 382 GNUNET_h2s (&keys[i].h_rsa.hash)); 383 success = true; 384 break; 385 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 386 /* This 'failure' is expected, we're testing also for the 387 error handling! */ 388 if ( (GNUNET_TIME_relative_is_zero ( 389 GNUNET_TIME_absolute_get_remaining ( 390 keys[i].start_time.abs_time))) && 391 (GNUNET_TIME_relative_cmp ( 392 GNUNET_TIME_absolute_get_duration ( 393 keys[i].start_time.abs_time), 394 <, 395 keys[i].validity_duration)) ) 396 { 397 /* key should have worked! */ 398 GNUNET_break (0); 399 return 6; 400 } 401 break; 402 default: 403 /* unexpected error */ 404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 405 "Unexpected error %d at %s:%u\n", 406 ec, 407 __FILE__, 408 __LINE__); 409 return 7; 410 } 411 } 412 if (! success) 413 { 414 /* no valid key for signing found, also bad */ 415 GNUNET_break (0); 416 return 16; 417 } 418 419 /* check signing does not work if the key is unknown */ 420 { 421 struct TALER_RsaPubHashP rnd; 422 struct TALER_CRYPTO_RsaSignRequest rsr = { 423 .h_rsa = &rnd, 424 .msg = "Hello", 425 .msg_size = strlen ("Hello") 426 }; 427 428 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 429 &rnd, 430 sizeof (rnd)); 431 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 432 1, 433 &rsr, 434 &ds); 435 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 436 { 437 if (TALER_EC_NONE == ec) 438 TALER_blinded_denom_sig_free (&ds); 439 GNUNET_break (0); 440 return 17; 441 } 442 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 443 "Signing with invalid key %s failed as desired\n", 444 GNUNET_h2s (&rnd.hash)); 445 } 446 return 0; 447 } 448 449 450 /** 451 * Test batch signing logic. 452 * 453 * @param dh handle to the helper 454 * @param batch_size how large should the batch be 455 * @param check_sigs also check unknown key and signatures 456 * @return 0 on success 457 */ 458 static int 459 test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 460 unsigned int batch_size, 461 bool check_sigs) 462 { 463 struct TALER_BlindedDenominationSignature ds[batch_size]; 464 enum TALER_ErrorCode ec; 465 bool success = false; 466 struct TALER_PlanchetMasterSecretP ps[batch_size]; 467 const struct TALER_ExchangeBlindingValues *alg_values; 468 struct TALER_AgeCommitmentHashP ach[batch_size]; 469 struct TALER_CoinPubHashP c_hash[batch_size]; 470 struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size]; 471 union GNUNET_CRYPTO_BlindingSecretP bks[batch_size]; 472 473 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, 474 &ps, 475 sizeof (ps)); 476 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 477 &ach, 478 sizeof(ach)); 479 alg_values = TALER_denom_ewv_rsa_singleton (); 480 for (unsigned int i = 0; i<batch_size; i++) 481 { 482 TALER_planchet_setup_coin_priv (&ps[i], 483 alg_values, 484 &coin_priv[i]); 485 TALER_planchet_blinding_secret_create (&ps[i], 486 alg_values, 487 &bks[i]); 488 } 489 for (unsigned int k = 0; k<MAX_KEYS; k++) 490 { 491 if (success && ! check_sigs) 492 break; /* only do one round */ 493 if (! keys[k].valid) 494 continue; 495 if (GNUNET_CRYPTO_BSA_RSA != 496 keys[k].denom_pub.bsign_pub_key->cipher) 497 continue; 498 { 499 struct TALER_PlanchetDetail pd[batch_size]; 500 struct TALER_CRYPTO_RsaSignRequest rsr[batch_size]; 501 502 for (unsigned int i = 0; i<batch_size; i++) 503 { 504 GNUNET_assert (GNUNET_YES == 505 TALER_planchet_prepare (&keys[k].denom_pub, 506 alg_values, 507 &bks[i], 508 NULL, 509 &coin_priv[i], 510 &ach[i], 511 &c_hash[i], 512 &pd[i])); 513 rsr[i].h_rsa 514 = &keys[k].h_rsa; 515 rsr[i].msg 516 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 517 blinded_msg; 518 rsr[i].msg_size 519 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 520 blinded_msg_size; 521 } 522 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 523 batch_size, 524 rsr, 525 ds); 526 for (unsigned int i = 0; i<batch_size; i++) 527 { 528 if (TALER_EC_NONE == ec) 529 GNUNET_break (GNUNET_CRYPTO_BSA_RSA == 530 ds[i].blinded_sig->cipher); 531 TALER_blinded_planchet_free (&pd[i].blinded_planchet); 532 } 533 } 534 switch (ec) 535 { 536 case TALER_EC_NONE: 537 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 538 keys[k].start_time.abs_time), 539 >, 540 GNUNET_TIME_UNIT_SECONDS)) 541 { 542 /* key worked too early */ 543 GNUNET_break (0); 544 return 4; 545 } 546 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 547 keys[k].start_time.abs_time), 548 >, 549 keys[k].validity_duration)) 550 { 551 /* key worked too later */ 552 GNUNET_break (0); 553 return 5; 554 } 555 for (unsigned int i = 0; i<batch_size; i++) 556 { 557 struct TALER_DenominationSignature rs; 558 559 if (check_sigs) 560 { 561 if (GNUNET_OK != 562 TALER_denom_sig_unblind (&rs, 563 &ds[i], 564 &bks[i], 565 &c_hash[i], 566 alg_values, 567 &keys[k].denom_pub)) 568 { 569 GNUNET_break (0); 570 return 6; 571 } 572 } 573 TALER_blinded_denom_sig_free (&ds[i]); 574 if (check_sigs) 575 { 576 if (GNUNET_OK != 577 TALER_denom_pub_verify (&keys[k].denom_pub, 578 &rs, 579 &c_hash[i])) 580 { 581 /* signature invalid */ 582 GNUNET_break (0); 583 TALER_denom_sig_free (&rs); 584 return 7; 585 } 586 TALER_denom_sig_free (&rs); 587 } 588 } 589 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 590 "Received valid signature for key %s\n", 591 GNUNET_h2s (&keys[k].h_rsa.hash)); 592 success = true; 593 break; 594 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 595 /* This 'failure' is expected, we're testing also for the 596 error handling! */ 597 for (unsigned int i = 0; i<batch_size; i++) 598 TALER_blinded_denom_sig_free (&ds[i]); 599 if ( (GNUNET_TIME_relative_is_zero ( 600 GNUNET_TIME_absolute_get_remaining ( 601 keys[k].start_time.abs_time))) && 602 (GNUNET_TIME_relative_cmp ( 603 GNUNET_TIME_absolute_get_duration ( 604 keys[k].start_time.abs_time), 605 <, 606 keys[k].validity_duration)) ) 607 { 608 /* key should have worked! */ 609 GNUNET_break (0); 610 return 6; 611 } 612 break; 613 case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN: 614 for (unsigned int i = 0; i<batch_size; i++) 615 TALER_blinded_denom_sig_free (&ds[i]); 616 break; 617 default: 618 /* unexpected error */ 619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 620 "Unexpected error %d at %s:%u\n", 621 ec, 622 __FILE__, 623 __LINE__); 624 for (unsigned int i = 0; i<batch_size; i++) 625 TALER_blinded_denom_sig_free (&ds[i]); 626 return 7; 627 } 628 } 629 if (! success) 630 { 631 /* no valid key for signing found, also bad */ 632 GNUNET_break (0); 633 return 16; 634 } 635 636 /* check signing does not work if the key is unknown */ 637 if (check_sigs) 638 { 639 struct TALER_RsaPubHashP rnd; 640 struct TALER_CRYPTO_RsaSignRequest rsr = { 641 .h_rsa = &rnd, 642 .msg = "Hello", 643 .msg_size = strlen ("Hello") 644 }; 645 646 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 647 &rnd, 648 sizeof (rnd)); 649 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 650 1, 651 &rsr, 652 ds); 653 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 654 { 655 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 656 "Signing with invalid key returned unexpected status %d\n", 657 ec); 658 if (TALER_EC_NONE == ec) 659 TALER_blinded_denom_sig_free (ds); 660 GNUNET_break (0); 661 return 17; 662 } 663 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 664 "Signing with invalid key %s failed as desired\n", 665 GNUNET_h2s (&rnd.hash)); 666 } 667 return 0; 668 } 669 670 671 /** 672 * Benchmark signing logic. 673 * 674 * @param dh handle to the helper 675 * @return 0 on success 676 */ 677 static int 678 perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 679 const char *type) 680 { 681 struct TALER_BlindedDenominationSignature ds; 682 enum TALER_ErrorCode ec; 683 struct GNUNET_TIME_Relative duration; 684 struct TALER_PlanchetMasterSecretP ps; 685 struct TALER_CoinSpendPrivateKeyP coin_priv; 686 struct TALER_AgeCommitmentHashP ach; 687 union GNUNET_CRYPTO_BlindingSecretP bks; 688 const struct TALER_ExchangeBlindingValues *alg_values 689 = TALER_denom_ewv_rsa_singleton (); 690 691 TALER_planchet_master_setup_random (&ps); 692 TALER_planchet_setup_coin_priv (&ps, 693 alg_values, 694 &coin_priv); 695 TALER_planchet_blinding_secret_create (&ps, 696 alg_values, 697 &bks); 698 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 699 &ach, 700 sizeof(ach)); 701 duration = GNUNET_TIME_UNIT_ZERO; 702 TALER_CRYPTO_helper_rsa_poll (dh); 703 for (unsigned int j = 0; j<NUM_SIGN_PERFS;) 704 { 705 for (unsigned int i = 0; i<MAX_KEYS; i++) 706 { 707 if (! keys[i].valid) 708 continue; 709 if (GNUNET_CRYPTO_BSA_RSA != 710 keys[i].denom_pub.bsign_pub_key->cipher) 711 continue; 712 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 713 keys[i].start_time.abs_time), 714 >, 715 GNUNET_TIME_UNIT_SECONDS)) 716 continue; 717 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 718 keys[i].start_time.abs_time), 719 >, 720 keys[i].validity_duration)) 721 continue; 722 { 723 struct TALER_CoinPubHashP c_hash; 724 struct TALER_PlanchetDetail pd; 725 726 GNUNET_assert (GNUNET_YES == 727 TALER_planchet_prepare (&keys[i].denom_pub, 728 alg_values, 729 &bks, 730 NULL, 731 &coin_priv, 732 &ach, 733 &c_hash, 734 &pd)); 735 /* use this key as long as it works */ 736 while (1) 737 { 738 struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get (); 739 struct GNUNET_TIME_Relative delay; 740 struct TALER_CRYPTO_RsaSignRequest rsr = { 741 .h_rsa = &keys[i].h_rsa, 742 .msg = 743 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 744 blinded_msg, 745 .msg_size = 746 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 747 blinded_msg_size 748 }; 749 750 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 751 1, 752 &rsr, 753 &ds); 754 if (TALER_EC_NONE != ec) 755 break; 756 delay = GNUNET_TIME_absolute_get_duration (start); 757 duration = GNUNET_TIME_relative_add (duration, 758 delay); 759 TALER_blinded_denom_sig_free (&ds); 760 j++; 761 if (NUM_SIGN_PERFS <= j) 762 break; 763 } 764 TALER_blinded_planchet_free (&pd.blinded_planchet); 765 } 766 } /* for i */ 767 } /* for j */ 768 fprintf (stderr, 769 "%u (%s) signature operations took %s\n", 770 (unsigned int) NUM_SIGN_PERFS, 771 type, 772 GNUNET_STRINGS_relative_time_to_string (duration, 773 GNUNET_YES)); 774 return 0; 775 } 776 777 778 /** 779 * Parallel signing logic. 780 * 781 * @param esh handle to the helper 782 * @return 0 on success 783 */ 784 static int 785 par_signing (struct GNUNET_CONFIGURATION_Handle *cfg) 786 { 787 struct GNUNET_TIME_Absolute start; 788 struct GNUNET_TIME_Relative duration; 789 pid_t pids[NUM_CORES]; 790 struct TALER_CRYPTO_RsaDenominationHelper *dh; 791 792 start = GNUNET_TIME_absolute_get (); 793 for (unsigned int i = 0; i<NUM_CORES; i++) 794 { 795 pids[i] = fork (); 796 num_keys = 0; 797 GNUNET_assert (-1 != pids[i]); 798 if (0 == pids[i]) 799 { 800 int ret; 801 802 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 803 "taler-exchange", 804 &key_cb, 805 NULL); 806 GNUNET_assert (NULL != dh); 807 ret = perf_signing (dh, 808 "parallel"); 809 TALER_CRYPTO_helper_rsa_disconnect (dh); 810 free_keys (); 811 exit (ret); 812 } 813 } 814 for (unsigned int i = 0; i<NUM_CORES; i++) 815 { 816 int wstatus; 817 818 GNUNET_assert (pids[i] == 819 waitpid (pids[i], 820 &wstatus, 821 0)); 822 } 823 duration = GNUNET_TIME_absolute_get_duration (start); 824 fprintf (stderr, 825 "%u (parallel) signature operations took %s (total real time)\n", 826 (unsigned int) NUM_SIGN_PERFS * NUM_CORES, 827 GNUNET_STRINGS_relative_time_to_string (duration, 828 GNUNET_YES)); 829 return 0; 830 } 831 832 833 /** 834 * Main entry point into the test logic with the helper already running. 835 */ 836 static int 837 run_test (void) 838 { 839 struct GNUNET_CONFIGURATION_Handle *cfg; 840 struct TALER_CRYPTO_RsaDenominationHelper *dh; 841 struct timespec req = { 842 .tv_nsec = 250000000 843 }; 844 int ret; 845 846 cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ()); 847 if (GNUNET_OK != 848 GNUNET_CONFIGURATION_load (cfg, 849 "test_helper_rsa.conf")) 850 { 851 GNUNET_break (0); 852 return 77; 853 } 854 855 fprintf (stderr, 856 "Waiting for helper to start ... "); 857 for (unsigned int i = 0; i<100; i++) 858 { 859 nanosleep (&req, 860 NULL); 861 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 862 "taler-exchange", 863 &key_cb, 864 NULL); 865 if (NULL != dh) 866 break; 867 fprintf (stderr, "."); 868 } 869 if (NULL == dh) 870 { 871 fprintf (stderr, 872 "\nFAILED: timeout trying to connect to helper\n"); 873 GNUNET_CONFIGURATION_destroy (cfg); 874 return 1; 875 } 876 if (0 == num_keys) 877 { 878 fprintf (stderr, 879 "\nFAILED: timeout trying to connect to helper\n"); 880 TALER_CRYPTO_helper_rsa_disconnect (dh); 881 GNUNET_CONFIGURATION_destroy (cfg); 882 return 1; 883 } 884 fprintf (stderr, 885 " Done (%u keys)\n", 886 num_keys); 887 ret = 0; 888 if (0 == ret) 889 ret = test_revocation (dh); 890 if (0 == ret) 891 ret = test_signing (dh); 892 if (0 == ret) 893 ret = test_batch_signing (dh, 894 2, 895 true); 896 if (0 == ret) 897 ret = test_batch_signing (dh, 898 64, 899 true); 900 for (unsigned int i = 0; i<4; i++) 901 { 902 static unsigned int batches[] = { 1, 4, 16, 64 }; 903 unsigned int batch_size = batches[i]; 904 struct GNUNET_TIME_Absolute start; 905 struct GNUNET_TIME_Relative duration; 906 907 start = GNUNET_TIME_absolute_get (); 908 if (0 != ret) 909 break; 910 ret = test_batch_signing (dh, 911 batch_size, 912 false); 913 duration = GNUNET_TIME_absolute_get_duration (start); 914 fprintf (stderr, 915 "%4u (batch) signature operations took %s (total real time)\n", 916 (unsigned int) batch_size, 917 GNUNET_STRINGS_relative_time_to_string (duration, 918 GNUNET_YES)); 919 } 920 if (0 == ret) 921 ret = perf_signing (dh, 922 "sequential"); 923 TALER_CRYPTO_helper_rsa_disconnect (dh); 924 free_keys (); 925 if (0 == ret) 926 ret = par_signing (cfg); 927 /* clean up our state */ 928 GNUNET_CONFIGURATION_destroy (cfg); 929 return ret; 930 } 931 932 933 int 934 main (int argc, 935 const char *const argv[]) 936 { 937 const char *loglevel = "WARNING"; 938 struct GNUNET_Process *helper; 939 char *libexec_dir; 940 char *binary_name; 941 int ret; 942 enum GNUNET_OS_ProcessStatusType type; 943 unsigned long code; 944 945 (void) argc; 946 (void) argv; 947 unsetenv ("XDG_DATA_HOME"); 948 unsetenv ("XDG_CONFIG_HOME"); 949 GNUNET_log_setup ("test-helper-rsa", 950 loglevel, 951 NULL); 952 libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (), 953 GNUNET_OS_IPK_BINDIR); 954 GNUNET_asprintf (&binary_name, 955 "%s/%s", 956 libexec_dir, 957 "taler-exchange-secmod-rsa"); 958 GNUNET_free (libexec_dir); 959 helper = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR); 960 if (GNUNET_OK != 961 GNUNET_process_run_command_va (helper, 962 binary_name, 963 binary_name, 964 "-c", 965 "test_helper_rsa.conf", 966 "-L", 967 loglevel, 968 NULL)) 969 { 970 GNUNET_process_destroy (helper); 971 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 972 "exec", 973 binary_name); 974 GNUNET_free (binary_name); 975 return 77; 976 } 977 GNUNET_free (binary_name); 978 ret = run_test (); 979 980 GNUNET_break (GNUNET_OK == 981 GNUNET_process_kill (helper, 982 SIGTERM)); 983 if (GNUNET_OK != 984 GNUNET_process_wait (helper, 985 true, 986 &type, 987 &code)) 988 { 989 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 990 "Helper process did not die voluntarily, killing hard\n"); 991 GNUNET_break (GNUNET_OK == 992 GNUNET_process_kill (helper, 993 SIGKILL)); 994 ret = 4; 995 } 996 else if ( (GNUNET_OS_PROCESS_EXITED != type) || 997 (0 != code) ) 998 { 999 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1000 "Helper died with unexpected status %d/%d\n", 1001 (int) type, 1002 (int) code); 1003 ret = 5; 1004 } 1005 GNUNET_process_destroy (helper); 1006 return ret; 1007 } 1008 1009 1010 /* end of test_helper_rsa.c */