secmod_rsa.c (64048B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2026 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/secmod_rsa.c 18 * @brief Standalone process to perform private key RSA operations 19 * @author Christian Grothoff 20 * 21 * Key design points: 22 * - EVERY thread of the exchange will have its own pair of connections to the 23 * crypto helpers. This way, every thread will also have its own /keys state 24 * and avoid the need to synchronize on those. 25 * - auditor signatures and master signatures are to be kept in the exchange DB, 26 * and merged with the public keys of the helper by the exchange HTTPD! 27 * - the main loop of the helper is SINGLE-THREADED, but there are 28 * threads for crypto-workers which do the signing in parallel, one per client. 29 * - thread-safety: signing happens in parallel, thus when REMOVING private keys, 30 * we must ensure that all signers are done before we fully free() the 31 * private key. This is done by reference counting (as work is always 32 * assigned and collected by the main thread). 33 */ 34 #include "platform.h" 35 #include "taler/taler_util.h" 36 #include "secmod_rsa.h" 37 #include <gcrypt.h> 38 #include <pthread.h> 39 #include "taler/taler_error_codes.h" 40 #include "taler/taler_signatures.h" 41 #include "secmod_common.h" 42 #include <poll.h> 43 44 45 /** 46 * Information we keep per denomination. 47 */ 48 struct Denomination; 49 50 51 /** 52 * One particular denomination key. 53 */ 54 struct DenominationKey 55 { 56 57 /** 58 * Kept in a DLL of the respective denomination. Sorted by anchor time. 59 */ 60 struct DenominationKey *next; 61 62 /** 63 * Kept in a DLL of the respective denomination. Sorted by anchor time. 64 */ 65 struct DenominationKey *prev; 66 67 /** 68 * Denomination this key belongs to. 69 */ 70 struct Denomination *denom; 71 72 /** 73 * Name of the file this key is stored under. 74 */ 75 char *filename; 76 77 /** 78 * The private key of the denomination. 79 */ 80 struct GNUNET_CRYPTO_RsaPrivateKey *denom_priv; 81 82 /** 83 * The public key of the denomination. 84 */ 85 struct GNUNET_CRYPTO_RsaPublicKey *denom_pub; 86 87 /** 88 * Message to transmit to clients to introduce this public key. 89 */ 90 struct TALER_CRYPTO_RsaKeyAvailableNotification *an; 91 92 /** 93 * Hash of this denomination's public key. 94 */ 95 struct TALER_RsaPubHashP h_rsa; 96 97 /** 98 * Time at which this key is supposed to become valid. 99 */ 100 struct GNUNET_TIME_Timestamp anchor_start; 101 102 /** 103 * Time at which this key is supposed to expire (exclusive). 104 */ 105 struct GNUNET_TIME_Timestamp anchor_end; 106 107 /** 108 * Generation when this key was created or revoked. 109 */ 110 uint64_t key_gen; 111 112 /** 113 * Reference counter. Counts the number of threads that are 114 * using this key at this time. 115 */ 116 unsigned int rc; 117 118 /** 119 * Flag set to true if this key has been purged and the memory 120 * must be freed as soon as @e rc hits zero. 121 */ 122 bool purge; 123 124 }; 125 126 127 struct Denomination 128 { 129 130 /** 131 * Kept in a DLL. 132 */ 133 struct Denomination *next; 134 135 /** 136 * Kept in a DLL. 137 */ 138 struct Denomination *prev; 139 140 /** 141 * Head of DLL of actual keys of this denomination. 142 */ 143 struct DenominationKey *keys_head; 144 145 /** 146 * Tail of DLL of actual keys of this denomination. 147 */ 148 struct DenominationKey *keys_tail; 149 150 /** 151 * How long can coins be withdrawn (generated)? Should be small 152 * enough to limit how many coins will be signed into existence with 153 * the same key, but large enough to still provide a reasonable 154 * anonymity set. 155 */ 156 struct GNUNET_TIME_Relative duration_withdraw; 157 158 /** 159 * Calendar interval the start of the validity period of our keys is 160 * rounded down to (and the end of the validity period rounded up to). 161 * #GNUNET_TIME_RI_NONE (the default) disables the rounding. Donau sets 162 * this to #GNUNET_TIME_RI_YEAR so that its keys are valid for exactly one 163 * calendar year (starting January 1st UTC), even if the key was generated 164 * in the middle of the year. 165 */ 166 enum GNUNET_TIME_RounderInterval anchor_round; 167 168 /** 169 * What is the configuration section of this denomination type? Also used 170 * for the directory name where the denomination keys are stored. 171 */ 172 char *section; 173 174 /** 175 * Length of (new) RSA keys (in bits). 176 */ 177 uint32_t rsa_keysize; 178 }; 179 180 181 /** 182 * A semaphore. 183 */ 184 struct Semaphore 185 { 186 /** 187 * Mutex for the semaphore. 188 */ 189 pthread_mutex_t mutex; 190 191 /** 192 * Condition variable for the semaphore. 193 */ 194 pthread_cond_t cv; 195 196 /** 197 * Counter of the semaphore. 198 */ 199 unsigned int ctr; 200 }; 201 202 203 /** 204 * Job in a batch sign request. 205 */ 206 struct BatchJob; 207 208 /** 209 * Handle for a thread that does work in batch signing. 210 */ 211 struct Worker 212 { 213 /** 214 * Kept in a DLL. 215 */ 216 struct Worker *prev; 217 218 /** 219 * Kept in a DLL. 220 */ 221 struct Worker *next; 222 223 /** 224 * Job this worker should do next. 225 */ 226 struct BatchJob *job; 227 228 /** 229 * Semaphore to signal the worker that a job is available. 230 */ 231 struct Semaphore sem; 232 233 /** 234 * Handle for this thread. 235 */ 236 pthread_t pt; 237 238 /** 239 * Set to true if the worker should terminate. 240 */ 241 bool do_shutdown; 242 }; 243 244 245 /** 246 * Job in a batch sign request. 247 */ 248 struct BatchJob 249 { 250 /** 251 * Request we are working on. 252 */ 253 const struct TALER_CRYPTO_SignRequest *sr; 254 255 /** 256 * Thread doing the work. 257 */ 258 struct Worker *worker; 259 260 /** 261 * Result with the signature. 262 */ 263 struct GNUNET_CRYPTO_RsaSignature *rsa_signature; 264 265 /** 266 * Semaphore to signal that the job is finished. 267 */ 268 struct Semaphore sem; 269 270 /** 271 * Computation status. 272 */ 273 enum TALER_ErrorCode ec; 274 275 }; 276 277 278 /** 279 * Head of DLL of workers ready for more work. 280 */ 281 static struct Worker *worker_head; 282 283 /** 284 * Tail of DLL of workers ready for more work. 285 */ 286 static struct Worker *worker_tail; 287 288 /** 289 * Lock for manipulating the worker DLL. 290 */ 291 static pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER; 292 293 /** 294 * Total number of workers that were started. 295 */ 296 static unsigned int workers; 297 298 /** 299 * Semaphore used to grab a worker. 300 */ 301 static struct Semaphore worker_sem; 302 303 /** 304 * Command-line options for various TALER_SECMOD_XXX_run() functions. 305 */ 306 static struct TALER_SECMOD_Options *globals; 307 308 /** 309 * Where do we store the keys? 310 */ 311 static char *keydir; 312 313 /** 314 * How much should coin creation (@e duration_withdraw) duration overlap 315 * with the next denomination? Basically, the starting time of two 316 * denominations is always @e duration_withdraw - #overlap_duration apart. 317 */ 318 static struct GNUNET_TIME_Relative overlap_duration; 319 320 /** 321 * How long into the future do we pre-generate keys? 322 */ 323 static struct GNUNET_TIME_Relative lookahead_sign; 324 325 /** 326 * All of our denominations, in a DLL. Sorted? 327 */ 328 static struct Denomination *denom_head; 329 330 /** 331 * All of our denominations, in a DLL. Sorted? 332 */ 333 static struct Denomination *denom_tail; 334 335 /** 336 * Map of hashes of public (RSA) keys to `struct DenominationKey *` 337 * with the respective private keys. 338 */ 339 static struct GNUNET_CONTAINER_MultiHashMap *keys; 340 341 /** 342 * Task run to generate new keys. 343 */ 344 static struct GNUNET_SCHEDULER_Task *keygen_task; 345 346 /** 347 * Lock for the keys queue. 348 */ 349 static pthread_mutex_t keys_lock = PTHREAD_MUTEX_INITIALIZER; 350 351 /** 352 * Current key generation. 353 */ 354 static uint64_t key_gen; 355 356 357 /** 358 * Generate the announcement message for @a dk. 359 * 360 * @param[in,out] dk denomination key to generate the announcement for 361 */ 362 static void 363 generate_response (struct DenominationKey *dk) 364 { 365 struct Denomination *denom = dk->denom; 366 size_t nlen = strlen (denom->section) + 1; 367 struct TALER_CRYPTO_RsaKeyAvailableNotification *an; 368 size_t buf_len; 369 void *buf; 370 void *p; 371 size_t tlen; 372 struct GNUNET_TIME_Relative effective_duration; 373 374 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub, 375 &buf); 376 GNUNET_assert (buf_len < UINT16_MAX); 377 GNUNET_assert (nlen < UINT16_MAX); 378 tlen = buf_len + nlen + sizeof (*an); 379 GNUNET_assert (tlen < UINT16_MAX); 380 an = GNUNET_malloc (tlen); 381 an->header.size = htons ((uint16_t) tlen); 382 an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL); 383 an->pub_size = htons ((uint16_t) buf_len); 384 an->section_name_len = htons ((uint16_t) nlen); 385 an->anchor_time = GNUNET_TIME_timestamp_hton (dk->anchor_start); 386 /* Effective duration is based on denum->duration_withdraw + overlap, 387 but we may have shifted the 'anchor_end' to align them, thus the 388 only correct way to determine it is: */ 389 effective_duration = GNUNET_TIME_absolute_get_difference ( 390 dk->anchor_start.abs_time, 391 dk->anchor_end.abs_time); 392 an->duration_withdraw = GNUNET_TIME_relative_hton (effective_duration); 393 394 TALER_exchange_secmod_rsa_sign (&dk->h_rsa, 395 denom->section, 396 dk->anchor_start, 397 effective_duration, 398 &TES_smpriv, 399 &an->secm_sig); 400 an->secm_pub = TES_smpub; 401 p = (void *) &an[1]; 402 GNUNET_memcpy (p, 403 buf, 404 buf_len); 405 GNUNET_free (buf); 406 GNUNET_memcpy (p + buf_len, 407 denom->section, 408 nlen); 409 dk->an = an; 410 } 411 412 413 /** 414 * Do the actual signing work. 415 * 416 * @param h_rsa key to sign with 417 * @param bm blinded message to sign 418 * @param[out] rsa_signaturep set to the RSA signature 419 * @return #TALER_EC_NONE on success 420 */ 421 static enum TALER_ErrorCode 422 do_sign (const struct TALER_RsaPubHashP *h_rsa, 423 const struct GNUNET_CRYPTO_RsaBlindedMessage *bm, 424 struct GNUNET_CRYPTO_RsaSignature **rsa_signaturep) 425 { 426 struct DenominationKey *dk; 427 struct GNUNET_CRYPTO_RsaSignature *rsa_signature; 428 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 429 430 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 431 dk = GNUNET_CONTAINER_multihashmap_get (keys, 432 &h_rsa->hash); 433 if (NULL == dk) 434 { 435 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 436 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 437 "Signing request failed, denomination key %s unknown\n", 438 GNUNET_h2s (&h_rsa->hash)); 439 return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; 440 } 441 if (dk->purge) 442 { 443 /* key was revoked, it must not be used for signing anymore */ 444 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 445 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 446 "Signing request failed, denomination key %s was revoked\n", 447 GNUNET_h2s (&h_rsa->hash)); 448 return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED; 449 } 450 if (GNUNET_TIME_absolute_is_future (dk->anchor_start.abs_time)) 451 { 452 /* it is too early */ 453 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 454 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 455 "Signing request failed, denomination key %s is not yet valid (%llu)\n", 456 GNUNET_h2s (&h_rsa->hash), 457 (unsigned long long) dk->anchor_start.abs_time.abs_value_us); 458 return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY; 459 } 460 if (GNUNET_TIME_absolute_is_past (dk->anchor_end.abs_time)) 461 { 462 /* it is too late; now, usually we should never get here 463 as we delete upon expiration, so this is just conservative */ 464 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 465 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 466 "Signing request failed, denomination key %s is expired (%llu)\n", 467 GNUNET_h2s (&h_rsa->hash), 468 (unsigned long long) dk->anchor_end.abs_time.abs_value_us); 469 /* usually we delete upon expiratoin, hence same EC */ 470 return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; 471 } 472 473 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 474 "Received request to sign over %u bytes with key %s\n", 475 (unsigned int) bm->blinded_msg_size, 476 GNUNET_h2s (&h_rsa->hash)); 477 GNUNET_assert (dk->rc < UINT_MAX); 478 dk->rc++; 479 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 480 rsa_signature 481 = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv, 482 bm); 483 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 484 GNUNET_assert (dk->rc > 0); 485 dk->rc--; 486 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 487 if (NULL == rsa_signature) 488 { 489 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 490 "Signing request failed, worker failed to produce signature\n"); 491 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 492 } 493 494 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 495 "Sending RSA signature after %s\n", 496 GNUNET_TIME_relative2s ( 497 GNUNET_TIME_absolute_get_duration (now), 498 GNUNET_YES)); 499 *rsa_signaturep = rsa_signature; 500 return TALER_EC_NONE; 501 } 502 503 504 /** 505 * Generate error response that signing failed. 506 * 507 * @param client client to send response to 508 * @param ec error code to include 509 * @return #GNUNET_OK on success 510 */ 511 static enum GNUNET_GenericReturnValue 512 fail_sign (struct TES_Client *client, 513 enum TALER_ErrorCode ec) 514 { 515 struct TALER_CRYPTO_SignFailure sf = { 516 .header.size = htons (sizeof (sf)), 517 .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE), 518 .ec = htonl (ec) 519 }; 520 521 return TES_transmit (client->csock, 522 &sf.header); 523 } 524 525 526 /** 527 * Generate signature response. 528 * 529 * @param client client to send response to 530 * @param[in] rsa_signature signature to send, freed by this function 531 * @return #GNUNET_OK on success 532 */ 533 static enum GNUNET_GenericReturnValue 534 send_signature (struct TES_Client *client, 535 struct GNUNET_CRYPTO_RsaSignature *rsa_signature) 536 { 537 struct TALER_CRYPTO_SignResponse *sr; 538 void *buf; 539 size_t buf_size; 540 size_t tsize; 541 enum GNUNET_GenericReturnValue ret; 542 543 buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature, 544 &buf); 545 GNUNET_CRYPTO_rsa_signature_free (rsa_signature); 546 tsize = sizeof (*sr) + buf_size; 547 GNUNET_assert (tsize < UINT16_MAX); 548 sr = GNUNET_malloc (tsize); 549 sr->header.size = htons (tsize); 550 sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE); 551 GNUNET_memcpy (&sr[1], 552 buf, 553 buf_size); 554 GNUNET_free (buf); 555 ret = TES_transmit (client->csock, 556 &sr->header); 557 GNUNET_free (sr); 558 return ret; 559 } 560 561 562 /** 563 * Handle @a client request @a sr to create signature. Create the 564 * signature using the respective key and return the result to 565 * the client. 566 * 567 * @param client the client making the request 568 * @param sr the request details 569 * @return #GNUNET_OK on success 570 */ 571 static enum GNUNET_GenericReturnValue 572 handle_sign_request (struct TES_Client *client, 573 const struct TALER_CRYPTO_SignRequest *sr) 574 { 575 struct GNUNET_CRYPTO_RsaBlindedMessage bm = { 576 .blinded_msg = (void *) &sr[1], 577 .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr) 578 }; 579 struct GNUNET_CRYPTO_RsaSignature *rsa_signature; 580 enum TALER_ErrorCode ec; 581 582 ec = do_sign (&sr->h_rsa, 583 &bm, 584 &rsa_signature); 585 if (TALER_EC_NONE != ec) 586 { 587 return fail_sign (client, 588 ec); 589 } 590 return send_signature (client, 591 rsa_signature); 592 } 593 594 595 /** 596 * Initialize a semaphore @a sem with a value of @a val. 597 * 598 * @param[out] sem semaphore to initialize 599 * @param val initial value of the semaphore 600 */ 601 static void 602 sem_init (struct Semaphore *sem, 603 unsigned int val) 604 { 605 GNUNET_assert (0 == 606 pthread_mutex_init (&sem->mutex, 607 NULL)); 608 GNUNET_assert (0 == 609 pthread_cond_init (&sem->cv, 610 NULL)); 611 sem->ctr = val; 612 } 613 614 615 /** 616 * Decrement semaphore, blocks until this is possible. 617 * 618 * @param[in,out] sem semaphore to decrement 619 */ 620 static void 621 sem_down (struct Semaphore *sem) 622 { 623 GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex)); 624 while (0 == sem->ctr) 625 { 626 pthread_cond_wait (&sem->cv, 627 &sem->mutex); 628 } 629 sem->ctr--; 630 GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex)); 631 } 632 633 634 /** 635 * Increment semaphore, blocks until this is possible. 636 * 637 * @param[in,out] sem semaphore to decrement 638 */ 639 static void 640 sem_up (struct Semaphore *sem) 641 { 642 GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex)); 643 sem->ctr++; 644 pthread_cond_signal (&sem->cv); 645 GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex)); 646 } 647 648 649 /** 650 * Release resources used by @a sem. 651 * 652 * @param[in] sem semaphore to release (except the memory itself) 653 */ 654 static void 655 sem_done (struct Semaphore *sem) 656 { 657 GNUNET_break (0 == pthread_cond_destroy (&sem->cv)); 658 GNUNET_break (0 == pthread_mutex_destroy (&sem->mutex)); 659 } 660 661 662 /** 663 * Main logic of a worker thread. Grabs work, does it, 664 * grabs more work. 665 * 666 * @param cls a `struct Worker *` 667 * @returns cls 668 */ 669 static void * 670 worker (void *cls) 671 { 672 struct Worker *w = cls; 673 674 while (true) 675 { 676 GNUNET_assert (0 == pthread_mutex_lock (&worker_lock)); 677 GNUNET_CONTAINER_DLL_insert (worker_head, 678 worker_tail, 679 w); 680 GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock)); 681 sem_up (&worker_sem); 682 sem_down (&w->sem); 683 if (w->do_shutdown) 684 break; 685 { 686 struct BatchJob *bj = w->job; 687 const struct TALER_CRYPTO_SignRequest *sr = bj->sr; 688 struct GNUNET_CRYPTO_RsaBlindedMessage bm = { 689 .blinded_msg = (void *) &sr[1], 690 .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr) 691 }; 692 693 bj->ec = do_sign (&sr->h_rsa, 694 &bm, 695 &bj->rsa_signature); 696 sem_up (&bj->sem); 697 w->job = NULL; 698 } 699 } 700 return w; 701 } 702 703 704 /** 705 * Start batch job @a bj to sign @a sr. 706 * 707 * @param sr signature request to answer 708 * @param[out] bj job data structure 709 */ 710 static void 711 start_job (const struct TALER_CRYPTO_SignRequest *sr, 712 struct BatchJob *bj) 713 { 714 sem_init (&bj->sem, 715 0); 716 bj->sr = sr; 717 sem_down (&worker_sem); 718 GNUNET_assert (0 == pthread_mutex_lock (&worker_lock)); 719 bj->worker = worker_head; 720 GNUNET_CONTAINER_DLL_remove (worker_head, 721 worker_tail, 722 bj->worker); 723 GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock)); 724 bj->worker->job = bj; 725 sem_up (&bj->worker->sem); 726 } 727 728 729 /** 730 * Finish a job @a bj for a @a client. 731 * 732 * @param client who made the request 733 * @param[in,out] bj job to finish 734 */ 735 static void 736 finish_job (struct TES_Client *client, 737 struct BatchJob *bj) 738 { 739 sem_down (&bj->sem); 740 sem_done (&bj->sem); 741 if (TALER_EC_NONE != bj->ec) 742 { 743 fail_sign (client, 744 bj->ec); 745 return; 746 } 747 GNUNET_assert (NULL != bj->rsa_signature); 748 send_signature (client, 749 bj->rsa_signature); 750 bj->rsa_signature = NULL; /* freed in send_signature */ 751 } 752 753 754 /** 755 * Handle @a client request @a sr to create a batch of signature. Creates the 756 * signatures using the respective key and return the results to the client. 757 * 758 * @param client the client making the request 759 * @param bsr the request details 760 * @return #GNUNET_OK on success 761 */ 762 static enum GNUNET_GenericReturnValue 763 handle_batch_sign_request (struct TES_Client *client, 764 const struct TALER_CRYPTO_BatchSignRequest *bsr) 765 { 766 uint32_t bs = ntohl (bsr->batch_size); 767 uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr); 768 const void *off = (const void *) &bsr[1]; 769 unsigned int idx = 0; 770 bool failure = false; 771 772 /* an empty batch would be answered with no message at all, 773 leaving the client waiting for a reply forever */ 774 if ( (0 == bs) || 775 (bs > TALER_MAX_COINS) ) 776 { 777 GNUNET_break_op (0); 778 return GNUNET_SYSERR; 779 } 780 { 781 struct BatchJob jobs[bs]; 782 783 while ( (idx < bs) && 784 (size > sizeof (struct TALER_CRYPTO_SignRequest)) ) 785 { 786 const struct TALER_CRYPTO_SignRequest *sr = off; 787 uint16_t s = ntohs (sr->header.size); 788 789 if ( (s > size) || 790 (s < sizeof (*sr)) ) 791 { 792 failure = true; 793 bs = idx; 794 break; 795 } 796 start_job (sr, 797 &jobs[idx++]); 798 off += s; 799 size -= s; 800 } 801 GNUNET_break_op (0 == size); 802 bs = GNUNET_MIN (bs, 803 idx); 804 for (unsigned int i = 0; i<bs; i++) 805 finish_job (client, 806 &jobs[i]); 807 } 808 if (failure) 809 { 810 struct TALER_CRYPTO_SignFailure sf = { 811 .header.size = htons (sizeof (sf)), 812 .header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE), 813 .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE) 814 }; 815 816 GNUNET_break (0); 817 return TES_transmit (client->csock, 818 &sf.header); 819 } 820 return GNUNET_OK; 821 } 822 823 824 /** 825 * Start worker thread for batch processing. 826 * 827 * @return #GNUNET_OK on success 828 */ 829 static enum GNUNET_GenericReturnValue 830 start_worker (void) 831 { 832 struct Worker *w; 833 834 w = GNUNET_new (struct Worker); 835 sem_init (&w->sem, 836 0); 837 if (0 != pthread_create (&w->pt, 838 NULL, 839 &worker, 840 w)) 841 { 842 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, 843 "pthread_create"); 844 GNUNET_free (w); 845 return GNUNET_SYSERR; 846 } 847 workers++; 848 return GNUNET_OK; 849 } 850 851 852 /** 853 * Stop all worker threads. 854 */ 855 static void 856 stop_workers (void) 857 { 858 while (workers > 0) 859 { 860 struct Worker *w; 861 void *result; 862 863 sem_down (&worker_sem); 864 GNUNET_assert (0 == pthread_mutex_lock (&worker_lock)); 865 w = worker_head; 866 GNUNET_CONTAINER_DLL_remove (worker_head, 867 worker_tail, 868 w); 869 GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock)); 870 w->do_shutdown = true; 871 sem_up (&w->sem); 872 pthread_join (w->pt, 873 &result); 874 GNUNET_assert (result == w); 875 sem_done (&w->sem); 876 GNUNET_free (w); 877 workers--; 878 } 879 } 880 881 882 /** 883 * Initialize key material for denomination key @a dk (also on disk). 884 * 885 * @param[in,out] dk denomination key to compute key material for 886 * @param position where in the DLL will the @a dk go 887 * @return #GNUNET_OK on success 888 */ 889 static enum GNUNET_GenericReturnValue 890 setup_key (struct DenominationKey *dk, 891 struct DenominationKey *position) 892 { 893 struct Denomination *denom = dk->denom; 894 struct GNUNET_CRYPTO_RsaPrivateKey *priv; 895 struct GNUNET_CRYPTO_RsaPublicKey *pub; 896 size_t buf_size; 897 void *buf; 898 899 priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize); 900 if (NULL == priv) 901 { 902 GNUNET_break (0); 903 GNUNET_SCHEDULER_shutdown (); 904 globals->global_ret = EXIT_FAILURE; 905 return GNUNET_SYSERR; 906 } 907 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); 908 if (NULL == pub) 909 { 910 GNUNET_break (0); 911 GNUNET_CRYPTO_rsa_private_key_free (priv); 912 return GNUNET_SYSERR; 913 } 914 buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv, 915 &buf); 916 GNUNET_CRYPTO_rsa_public_key_hash (pub, 917 &dk->h_rsa.hash); 918 GNUNET_asprintf ( 919 &dk->filename, 920 "%s/%s/%llu-%llu", 921 keydir, 922 denom->section, 923 (unsigned long long) (dk->anchor_start.abs_time.abs_value_us 924 / GNUNET_TIME_UNIT_SECONDS.rel_value_us), 925 (unsigned long long) (dk->anchor_end.abs_time.abs_value_us 926 / GNUNET_TIME_UNIT_SECONDS.rel_value_us)); 927 if (GNUNET_OK != 928 GNUNET_DISK_fn_write (dk->filename, 929 buf, 930 buf_size, 931 GNUNET_DISK_PERM_USER_READ)) 932 { 933 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 934 "write", 935 dk->filename); 936 GNUNET_free (dk->filename); 937 GNUNET_free (buf); 938 GNUNET_CRYPTO_rsa_private_key_free (priv); 939 GNUNET_CRYPTO_rsa_public_key_free (pub); 940 return GNUNET_SYSERR; 941 } 942 GNUNET_free (buf); 943 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 944 "Setup fresh private key %s at %s in `%s' (generation #%llu)\n", 945 GNUNET_h2s (&dk->h_rsa.hash), 946 GNUNET_TIME_timestamp2s (dk->anchor_start), 947 dk->filename, 948 (unsigned long long) key_gen); 949 dk->denom_priv = priv; 950 dk->denom_pub = pub; 951 dk->key_gen = key_gen; 952 generate_response (dk); 953 if (GNUNET_OK != 954 GNUNET_CONTAINER_multihashmap_put ( 955 keys, 956 &dk->h_rsa.hash, 957 dk, 958 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) 959 { 960 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 961 "Duplicate private key created! Terminating.\n"); 962 GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv); 963 GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub); 964 GNUNET_free (dk->filename); 965 GNUNET_free (dk->an); 966 GNUNET_free (dk); 967 return GNUNET_SYSERR; 968 } 969 GNUNET_CONTAINER_DLL_insert_after (denom->keys_head, 970 denom->keys_tail, 971 position, 972 dk); 973 return GNUNET_OK; 974 } 975 976 977 /** 978 * The withdraw period of a key @a dk has expired. Purge it. 979 * 980 * @param[in] dk expired denomination key to purge 981 */ 982 static void 983 purge_key (struct DenominationKey *dk) 984 { 985 if (dk->purge) 986 return; 987 if (0 != unlink (dk->filename)) 988 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 989 "unlink", 990 dk->filename); 991 GNUNET_free (dk->filename); 992 dk->purge = true; 993 dk->key_gen = key_gen; 994 } 995 996 997 /** 998 * A @a client informs us that a key has been revoked. 999 * Check if the key is still in use, and if so replace (!) 1000 * it with a fresh key. 1001 * 1002 * @param client the client making the request 1003 * @param rr the revocation request 1004 */ 1005 static enum GNUNET_GenericReturnValue 1006 handle_revoke_request (struct TES_Client *client, 1007 const struct TALER_CRYPTO_RevokeRequest *rr) 1008 { 1009 struct DenominationKey *dk; 1010 struct DenominationKey *ndk; 1011 struct Denomination *denom; 1012 1013 (void) client; 1014 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 1015 dk = GNUNET_CONTAINER_multihashmap_get (keys, 1016 &rr->h_rsa.hash); 1017 if (NULL == dk) 1018 { 1019 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1020 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1021 "Revocation request ignored, denomination key %s unknown\n", 1022 GNUNET_h2s (&rr->h_rsa.hash)); 1023 return GNUNET_OK; 1024 } 1025 if (dk->purge) 1026 { 1027 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1028 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1029 "Revocation request ignored, denomination key %s already revoked\n", 1030 GNUNET_h2s (&rr->h_rsa.hash)); 1031 return GNUNET_OK; 1032 } 1033 1034 key_gen++; 1035 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1036 "Revoking key %s, bumping generation to %llu\n", 1037 GNUNET_h2s (&rr->h_rsa.hash), 1038 (unsigned long long) key_gen); 1039 purge_key (dk); 1040 1041 /* Setup replacement key */ 1042 denom = dk->denom; 1043 ndk = GNUNET_new (struct DenominationKey); 1044 ndk->denom = denom; 1045 ndk->anchor_start = dk->anchor_start; 1046 ndk->anchor_end = dk->anchor_end; 1047 if (GNUNET_OK != 1048 setup_key (ndk, 1049 dk)) 1050 { 1051 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1052 GNUNET_break (0); 1053 GNUNET_SCHEDULER_shutdown (); 1054 globals->global_ret = EXIT_FAILURE; 1055 return GNUNET_SYSERR; 1056 } 1057 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1058 TES_wake_clients (); 1059 return GNUNET_OK; 1060 } 1061 1062 1063 /** 1064 * Handle @a hdr message received from @a client. 1065 * 1066 * @param client the client that received the message 1067 * @param hdr message that was received 1068 * @return #GNUNET_OK on success 1069 */ 1070 static enum GNUNET_GenericReturnValue 1071 rsa_work_dispatch (struct TES_Client *client, 1072 const struct GNUNET_MessageHeader *hdr) 1073 { 1074 uint16_t msize = ntohs (hdr->size); 1075 1076 switch (ntohs (hdr->type)) 1077 { 1078 case TALER_HELPER_RSA_MT_REQ_SIGN: 1079 if (msize <= sizeof (struct TALER_CRYPTO_SignRequest)) 1080 { 1081 GNUNET_break_op (0); 1082 return GNUNET_SYSERR; 1083 } 1084 return handle_sign_request ( 1085 client, 1086 (const struct TALER_CRYPTO_SignRequest *) hdr); 1087 case TALER_HELPER_RSA_MT_REQ_REVOKE: 1088 if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest)) 1089 { 1090 GNUNET_break_op (0); 1091 return GNUNET_SYSERR; 1092 } 1093 return handle_revoke_request ( 1094 client, 1095 (const struct TALER_CRYPTO_RevokeRequest *) hdr); 1096 case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN: 1097 if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest)) 1098 { 1099 GNUNET_break_op (0); 1100 return GNUNET_SYSERR; 1101 } 1102 return handle_batch_sign_request ( 1103 client, 1104 (const struct TALER_CRYPTO_BatchSignRequest *) hdr); 1105 default: 1106 GNUNET_break_op (0); 1107 return GNUNET_SYSERR; 1108 } 1109 } 1110 1111 1112 /** 1113 * Send our initial key set to @a client together with the 1114 * "sync" terminator. 1115 * 1116 * @param client the client to inform 1117 * @return #GNUNET_OK on success 1118 */ 1119 static enum GNUNET_GenericReturnValue 1120 rsa_client_init (struct TES_Client *client) 1121 { 1122 size_t obs = 0; 1123 char *buf; 1124 1125 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1126 "Initializing new client %p\n", 1127 client); 1128 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 1129 for (struct Denomination *denom = denom_head; 1130 NULL != denom; 1131 denom = denom->next) 1132 { 1133 for (struct DenominationKey *dk = denom->keys_head; 1134 NULL != dk; 1135 dk = dk->next) 1136 { 1137 GNUNET_assert (obs + ntohs (dk->an->header.size) 1138 > obs); 1139 obs += ntohs (dk->an->header.size); 1140 } 1141 } 1142 buf = GNUNET_malloc (obs); 1143 obs = 0; 1144 for (struct Denomination *denom = denom_head; 1145 NULL != denom; 1146 denom = denom->next) 1147 { 1148 for (struct DenominationKey *dk = denom->keys_head; 1149 NULL != dk; 1150 dk = dk->next) 1151 { 1152 GNUNET_memcpy (&buf[obs], 1153 dk->an, 1154 ntohs (dk->an->header.size)); 1155 GNUNET_assert (obs + ntohs (dk->an->header.size) 1156 > obs); 1157 obs += ntohs (dk->an->header.size); 1158 } 1159 } 1160 client->key_gen = key_gen; 1161 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1162 if (GNUNET_OK != 1163 TES_transmit_raw (client->csock, 1164 obs, 1165 buf)) 1166 { 1167 GNUNET_free (buf); 1168 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1169 "Client %p must have disconnected\n", 1170 client); 1171 return GNUNET_SYSERR; 1172 } 1173 GNUNET_free (buf); 1174 { 1175 struct GNUNET_MessageHeader synced = { 1176 .type = htons (TALER_HELPER_RSA_SYNCED), 1177 .size = htons (sizeof (synced)) 1178 }; 1179 1180 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1181 "Sending RSA SYNCED message to %p\n", 1182 client); 1183 if (GNUNET_OK != 1184 TES_transmit (client->csock, 1185 &synced)) 1186 { 1187 GNUNET_break (0); 1188 return GNUNET_SYSERR; 1189 } 1190 } 1191 return GNUNET_OK; 1192 } 1193 1194 1195 /** 1196 * Notify @a client about all changes to the keys since 1197 * the last generation known to the @a client. 1198 * 1199 * @param client the client to notify 1200 * @return #GNUNET_OK on success 1201 */ 1202 static enum GNUNET_GenericReturnValue 1203 rsa_update_client_keys (struct TES_Client *client) 1204 { 1205 size_t obs = 0; 1206 char *buf; 1207 enum GNUNET_GenericReturnValue ret; 1208 1209 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 1210 for (struct Denomination *denom = denom_head; 1211 NULL != denom; 1212 denom = denom->next) 1213 { 1214 for (struct DenominationKey *key = denom->keys_head; 1215 NULL != key; 1216 key = key->next) 1217 { 1218 if (key->key_gen <= client->key_gen) 1219 continue; 1220 if (key->purge) 1221 obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification); 1222 else 1223 obs += ntohs (key->an->header.size); 1224 } 1225 } 1226 if (0 == obs) 1227 { 1228 /* nothing to do */ 1229 client->key_gen = key_gen; 1230 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1231 return GNUNET_OK; 1232 } 1233 buf = GNUNET_malloc (obs); 1234 obs = 0; 1235 for (struct Denomination *denom = denom_head; 1236 NULL != denom; 1237 denom = denom->next) 1238 { 1239 for (struct DenominationKey *key = denom->keys_head; 1240 NULL != key; 1241 key = key->next) 1242 { 1243 if (key->key_gen <= client->key_gen) 1244 continue; 1245 if (key->purge) 1246 { 1247 struct TALER_CRYPTO_RsaKeyPurgeNotification pn = { 1248 .header.type = htons (TALER_HELPER_RSA_MT_PURGE), 1249 .header.size = htons (sizeof (pn)), 1250 .h_rsa = key->h_rsa 1251 }; 1252 1253 GNUNET_memcpy (&buf[obs], 1254 &pn, 1255 sizeof (pn)); 1256 GNUNET_assert (obs + sizeof (pn) 1257 > obs); 1258 obs += sizeof (pn); 1259 } 1260 else 1261 { 1262 GNUNET_memcpy (&buf[obs], 1263 key->an, 1264 ntohs (key->an->header.size)); 1265 GNUNET_assert (obs + ntohs (key->an->header.size) 1266 > obs); 1267 obs += ntohs (key->an->header.size); 1268 } 1269 } 1270 } 1271 client->key_gen = key_gen; 1272 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1273 ret = TES_transmit_raw (client->csock, 1274 obs, 1275 buf); 1276 GNUNET_free (buf); 1277 return ret; 1278 } 1279 1280 1281 /** 1282 * Create a new denomination key (we do not have enough). 1283 * 1284 * @param[in,out] denom denomination key to create 1285 * @param anchor_start when to start key signing validity 1286 * @param anchor_end when to end key signing validity 1287 * @return #GNUNET_OK on success 1288 */ 1289 static enum GNUNET_GenericReturnValue 1290 create_key (struct Denomination *denom, 1291 struct GNUNET_TIME_Timestamp anchor_start, 1292 struct GNUNET_TIME_Timestamp anchor_end) 1293 { 1294 struct DenominationKey *dk; 1295 1296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1297 "Creating new key for `%s' with start date %s\n", 1298 denom->section, 1299 GNUNET_TIME_timestamp2s (anchor_start)); 1300 dk = GNUNET_new (struct DenominationKey); 1301 dk->denom = denom; 1302 dk->anchor_start = anchor_start; 1303 dk->anchor_end = anchor_end; 1304 if (GNUNET_OK != 1305 setup_key (dk, 1306 denom->keys_tail)) 1307 { 1308 GNUNET_break (0); 1309 GNUNET_free (dk); 1310 GNUNET_SCHEDULER_shutdown (); 1311 globals->global_ret = EXIT_FAILURE; 1312 return GNUNET_SYSERR; 1313 } 1314 return GNUNET_OK; 1315 } 1316 1317 1318 /** 1319 * Obtain the maximum withdraw duration of all denominations. 1320 * 1321 * Must only be called while the #keys_lock is held. 1322 * 1323 * @return maximum withdraw duration, zero if there are no denominations 1324 */ 1325 static struct GNUNET_TIME_Relative 1326 get_maximum_duration (void) 1327 { 1328 struct GNUNET_TIME_Relative ret 1329 = GNUNET_TIME_UNIT_ZERO; 1330 1331 for (struct Denomination *denom = denom_head; 1332 NULL != denom; 1333 denom = denom->next) 1334 { 1335 ret = GNUNET_TIME_relative_max (ret, 1336 denom->duration_withdraw); 1337 } 1338 return ret; 1339 } 1340 1341 1342 /** 1343 * At what time do we need to next create keys if we just did? 1344 * 1345 * @return time when to next create keys if we just finished key generation 1346 */ 1347 static struct GNUNET_TIME_Absolute 1348 action_time (void) 1349 { 1350 struct GNUNET_TIME_Relative md = get_maximum_duration (); 1351 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 1352 uint64_t mod; 1353 1354 if (GNUNET_TIME_relative_is_zero (md)) 1355 return GNUNET_TIME_UNIT_FOREVER_ABS; 1356 mod = now.abs_value_us % md.rel_value_us; 1357 now.abs_value_us -= mod; 1358 return GNUNET_TIME_absolute_add (now, 1359 md); 1360 } 1361 1362 1363 /** 1364 * Remove all denomination keys of @a denom that have expired. 1365 * 1366 * @param[in,out] denom denomination family to remove keys for 1367 */ 1368 static void 1369 remove_expired_denomination_keys (struct Denomination *denom) 1370 { 1371 while ( (NULL != denom->keys_head) && 1372 GNUNET_TIME_absolute_is_past ( 1373 denom->keys_head->anchor_end.abs_time)) 1374 { 1375 struct DenominationKey *key = denom->keys_head; 1376 struct DenominationKey *nxt = key->next; 1377 1378 if (0 != key->rc) 1379 break; /* later */ 1380 GNUNET_CONTAINER_DLL_remove (denom->keys_head, 1381 denom->keys_tail, 1382 key); 1383 GNUNET_assert (GNUNET_OK == 1384 GNUNET_CONTAINER_multihashmap_remove ( 1385 keys, 1386 &key->h_rsa.hash, 1387 key)); 1388 if ( (! key->purge) && 1389 (0 != unlink (key->filename)) ) 1390 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 1391 "unlink", 1392 key->filename); 1393 GNUNET_free (key->filename); 1394 GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv); 1395 GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub); 1396 GNUNET_free (key->an); 1397 GNUNET_free (key); 1398 key = nxt; 1399 } 1400 } 1401 1402 1403 /** 1404 * Obtain the end anchor to use at this point. Uses the 1405 * #lookahead_sign and then rounds it up by the maximum 1406 * duration of any denomination to arrive at a globally 1407 * valid end-date. 1408 * 1409 * Must only be called while the #keys_lock is held. 1410 * 1411 * @return end anchor 1412 */ 1413 static struct GNUNET_TIME_Timestamp 1414 get_anchor_end (void) 1415 { 1416 struct GNUNET_TIME_Relative md = get_maximum_duration (); 1417 struct GNUNET_TIME_Absolute end 1418 = GNUNET_TIME_relative_to_absolute (lookahead_sign); 1419 uint64_t mod; 1420 1421 if (GNUNET_TIME_relative_is_zero (md)) 1422 return GNUNET_TIME_UNIT_ZERO_TS; 1423 /* Round up 'end' to a multiple of 'md' */ 1424 mod = end.abs_value_us % md.rel_value_us; 1425 end.abs_value_us -= mod; 1426 return GNUNET_TIME_absolute_to_timestamp ( 1427 GNUNET_TIME_absolute_add (end, 1428 md)); 1429 } 1430 1431 1432 /** 1433 * Create all denomination keys that are required for our 1434 * desired lookahead and that we do not yet have. 1435 * 1436 * @param[in,out] opt our options 1437 * @param[in,out] wake set to true if we should wake the clients 1438 */ 1439 static void 1440 create_missing_keys (struct TALER_SECMOD_Options *opt, 1441 bool *wake) 1442 { 1443 struct GNUNET_TIME_Timestamp start; 1444 struct GNUNET_TIME_Timestamp end; 1445 1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1447 "Updating denominations ...\n"); 1448 start = opt->global_now; 1449 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 1450 end = get_anchor_end (); 1451 for (struct Denomination *denom = denom_head; 1452 NULL != denom; 1453 denom = denom->next) 1454 { 1455 struct GNUNET_TIME_Timestamp anchor_start; 1456 struct GNUNET_TIME_Timestamp anchor_end; 1457 struct GNUNET_TIME_Timestamp next_end; 1458 bool finished = false; 1459 1460 remove_expired_denomination_keys (denom); 1461 if (NULL != denom->keys_tail) 1462 { 1463 anchor_start = denom->keys_tail->anchor_end; 1464 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1465 "Expanding keys of denomination `%s', last key %s valid for another %s\n", 1466 denom->section, 1467 GNUNET_h2s (&denom->keys_tail->h_rsa.hash), 1468 GNUNET_TIME_relative2s ( 1469 GNUNET_TIME_absolute_get_remaining ( 1470 anchor_start.abs_time), 1471 true)); 1472 } 1473 else 1474 { 1475 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1476 "Starting keys of denomination `%s'\n", 1477 denom->section); 1478 /* Round the very first anchor down to the configured calendar 1479 interval; subsequent anchors inherit the alignment from the 1480 (rounded up) end of the preceding key. The UTC variants are used 1481 so that the result does not depend on the time zone the secmod 1482 happens to run in. */ 1483 anchor_start = GNUNET_TIME_absolute_to_timestamp ( 1484 GNUNET_TIME_round_down_utc (start.abs_time, 1485 denom->anchor_round)); 1486 } 1487 finished = GNUNET_TIME_timestamp_cmp (anchor_start, 1488 >=, 1489 end); 1490 while (! finished) 1491 { 1492 /* Round the end of the validity period up to the configured calendar 1493 interval. As #GNUNET_TIME_UNIT_YEARS is 365 days, this is also what 1494 keeps the anchors from drifting off the calendar boundary across leap 1495 years. Without ANCHOR_ROUND, all of this is a no-op. */ 1496 anchor_end = GNUNET_TIME_absolute_to_timestamp ( 1497 GNUNET_TIME_round_up_utc ( 1498 GNUNET_TIME_absolute_add (anchor_start.abs_time, 1499 denom->duration_withdraw), 1500 denom->anchor_round)); 1501 next_end = GNUNET_TIME_absolute_to_timestamp ( 1502 GNUNET_TIME_round_up_utc ( 1503 GNUNET_TIME_absolute_add (anchor_end.abs_time, 1504 denom->duration_withdraw), 1505 denom->anchor_round)); 1506 if (GNUNET_TIME_timestamp_cmp (next_end, 1507 >, 1508 end)) 1509 { 1510 /* With ANCHOR_ROUND set the calendar interval already provides the 1511 alignment, and stretching the last key would make it cover more 1512 than the one interval it is supposed to cover. */ 1513 if (GNUNET_TIME_RI_NONE == denom->anchor_round) 1514 anchor_end = end; /* extend period to align end periods */ 1515 finished = true; 1516 } 1517 /* adjust start time down to ensure overlap */ 1518 anchor_start = GNUNET_TIME_absolute_to_timestamp ( 1519 GNUNET_TIME_absolute_subtract (anchor_start.abs_time, 1520 overlap_duration)); 1521 if (! *wake) 1522 { 1523 key_gen++; 1524 *wake = true; 1525 } 1526 if (GNUNET_OK != 1527 create_key (denom, 1528 anchor_start, 1529 anchor_end)) 1530 { 1531 GNUNET_break (0); 1532 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1533 globals->global_ret = EXIT_FAILURE; 1534 GNUNET_SCHEDULER_shutdown (); 1535 return; 1536 } 1537 anchor_start = anchor_end; 1538 } 1539 remove_expired_denomination_keys (denom); 1540 } 1541 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 1542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1543 "Updating denominations finished ...\n"); 1544 } 1545 1546 1547 /** 1548 * Task run periodically to expire keys and/or generate fresh ones. 1549 * 1550 * @param cls the `struct TALER_SECMOD_Options *` 1551 */ 1552 static void 1553 update_denominations (void *cls) 1554 { 1555 struct TALER_SECMOD_Options *opt = cls; 1556 struct GNUNET_TIME_Absolute at; 1557 bool wake = false; 1558 1559 (void) cls; 1560 keygen_task = NULL; 1561 /* update current time, global override no longer applies */ 1562 opt->global_now = GNUNET_TIME_timestamp_get (); 1563 create_missing_keys (opt, 1564 &wake); 1565 if (wake) 1566 TES_wake_clients (); 1567 at = action_time (); 1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1569 "Next key generation due at %s\n", 1570 GNUNET_TIME_absolute2s (at)); 1571 keygen_task = GNUNET_SCHEDULER_add_at (at, 1572 &update_denominations, 1573 opt); 1574 } 1575 1576 1577 /** 1578 * Parse private key of denomination @a denom in @a buf. 1579 * 1580 * @param[out] denom denomination of the key 1581 * @param filename name of the file we are parsing, for logging 1582 * @param buf key material 1583 * @param buf_size number of bytes in @a buf 1584 */ 1585 static void 1586 parse_key (struct Denomination *denom, 1587 const char *filename, 1588 const void *buf, 1589 size_t buf_size) 1590 { 1591 struct GNUNET_CRYPTO_RsaPrivateKey *priv; 1592 const char *anchor_s; 1593 char dummy; 1594 unsigned long long anchor_start_ll; 1595 unsigned long long anchor_end_ll; 1596 struct GNUNET_TIME_Timestamp anchor_start; 1597 struct GNUNET_TIME_Timestamp anchor_end; 1598 char *nf = NULL; 1599 1600 anchor_s = strrchr (filename, 1601 '/'); 1602 if (NULL == anchor_s) 1603 { 1604 /* File in a directory without '/' in the name, this makes no sense. */ 1605 GNUNET_break (0); 1606 return; 1607 } 1608 anchor_s++; 1609 if (2 != sscanf (anchor_s, 1610 "%llu-%llu%c", 1611 &anchor_start_ll, 1612 &anchor_end_ll, 1613 &dummy)) 1614 { 1615 /* try legacy mode */ 1616 if (1 != sscanf (anchor_s, 1617 "%llu%c", 1618 &anchor_start_ll, 1619 &dummy)) 1620 { 1621 /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */ 1622 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1623 "Filename `%s' invalid for key file, skipping\n", 1624 anchor_s); 1625 return; 1626 } 1627 anchor_start.abs_time.abs_value_us 1628 = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us; 1629 if (anchor_start_ll != anchor_start.abs_time.abs_value_us 1630 / GNUNET_TIME_UNIT_SECONDS.rel_value_us) 1631 { 1632 /* Integer overflow. Bad, invalid filename. */ 1633 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1634 "Integer overflow. Filename `%s' invalid for key file, skipping\n", 1635 anchor_s); 1636 return; 1637 } 1638 anchor_end 1639 = GNUNET_TIME_absolute_to_timestamp ( 1640 GNUNET_TIME_absolute_add (anchor_start.abs_time, 1641 denom->duration_withdraw)); 1642 GNUNET_asprintf ( 1643 &nf, 1644 "%s/%s/%llu-%llu", 1645 keydir, 1646 denom->section, 1647 anchor_start_ll, 1648 (unsigned long long) (anchor_end.abs_time.abs_value_us 1649 / GNUNET_TIME_UNIT_SECONDS.rel_value_us)); 1650 /* Try to fix the legacy filename */ 1651 if (0 != 1652 rename (filename, 1653 nf)) 1654 { 1655 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1656 "rename", 1657 filename); 1658 GNUNET_free (nf); 1659 } 1660 } 1661 else 1662 { 1663 anchor_start.abs_time.abs_value_us 1664 = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us; 1665 anchor_end.abs_time.abs_value_us 1666 = anchor_end_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us; 1667 if ( (anchor_start_ll != anchor_start.abs_time.abs_value_us 1668 / GNUNET_TIME_UNIT_SECONDS.rel_value_us) || 1669 (anchor_end_ll != anchor_end.abs_time.abs_value_us 1670 / GNUNET_TIME_UNIT_SECONDS.rel_value_us) ) 1671 { 1672 /* Integer overflow. Bad, invalid filename. */ 1673 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1674 "Integer overflow. Filename `%s' invalid for key file, skipping\n", 1675 anchor_s); 1676 return; 1677 } 1678 } 1679 priv = GNUNET_CRYPTO_rsa_private_key_decode (buf, 1680 buf_size); 1681 if (NULL == priv) 1682 { 1683 /* Parser failure. */ 1684 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1685 "File `%s' is malformed, skipping\n", 1686 (NULL == nf) ? filename : nf); 1687 GNUNET_free (nf); 1688 return; 1689 } 1690 1691 { 1692 struct GNUNET_CRYPTO_RsaPublicKey *pub; 1693 struct DenominationKey *dk; 1694 struct DenominationKey *before; 1695 1696 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); 1697 if (NULL == pub) 1698 { 1699 GNUNET_break (0); 1700 GNUNET_CRYPTO_rsa_private_key_free (priv); 1701 GNUNET_free (nf); 1702 return; 1703 } 1704 dk = GNUNET_new (struct DenominationKey); 1705 dk->denom_priv = priv; 1706 dk->denom = denom; 1707 dk->anchor_start = anchor_start; 1708 dk->anchor_end = anchor_end; 1709 dk->filename = (NULL == nf) ? GNUNET_strdup (filename) : nf; 1710 GNUNET_CRYPTO_rsa_public_key_hash (pub, 1711 &dk->h_rsa.hash); 1712 dk->denom_pub = pub; 1713 generate_response (dk); 1714 if (GNUNET_OK != 1715 GNUNET_CONTAINER_multihashmap_put ( 1716 keys, 1717 &dk->h_rsa.hash, 1718 dk, 1719 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) 1720 { 1721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1722 "Duplicate private key %s detected in file `%s'. Skipping.\n", 1723 GNUNET_h2s (&dk->h_rsa.hash), 1724 filename); 1725 GNUNET_CRYPTO_rsa_private_key_free (priv); 1726 GNUNET_CRYPTO_rsa_public_key_free (pub); 1727 GNUNET_free (dk->an); 1728 GNUNET_free (dk); 1729 return; 1730 } 1731 before = NULL; 1732 for (struct DenominationKey *pos = denom->keys_head; 1733 NULL != pos; 1734 pos = pos->next) 1735 { 1736 if (GNUNET_TIME_timestamp_cmp (pos->anchor_start, 1737 >, 1738 anchor_start)) 1739 break; 1740 before = pos; 1741 } 1742 GNUNET_CONTAINER_DLL_insert_after (denom->keys_head, 1743 denom->keys_tail, 1744 before, 1745 dk); 1746 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1747 "Imported key %s from `%s'\n", 1748 GNUNET_h2s (&dk->h_rsa.hash), 1749 filename); 1750 } 1751 } 1752 1753 1754 /** 1755 * Import a private key from @a filename for the denomination 1756 * given in @a cls. 1757 * 1758 * @param[in,out] cls a `struct Denomiantion` 1759 * @param filename name of a file in the directory 1760 * @return #GNUNET_OK (always, continue to iterate) 1761 */ 1762 static enum GNUNET_GenericReturnValue 1763 import_key (void *cls, 1764 const char *filename) 1765 { 1766 struct Denomination *denom = cls; 1767 struct GNUNET_DISK_FileHandle *fh; 1768 struct GNUNET_DISK_MapHandle *map; 1769 void *ptr; 1770 int fd; 1771 struct stat sbuf; 1772 1773 { 1774 struct stat lsbuf; 1775 1776 if (0 != lstat (filename, 1777 &lsbuf)) 1778 { 1779 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1780 "lstat", 1781 filename); 1782 return GNUNET_OK; 1783 } 1784 if (! S_ISREG (lsbuf.st_mode)) 1785 { 1786 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1787 "File `%s' is not a regular file, which is not allowed for private keys!\n", 1788 filename); 1789 return GNUNET_OK; 1790 } 1791 } 1792 1793 fd = open (filename, 1794 O_RDONLY | O_CLOEXEC); 1795 if (-1 == fd) 1796 { 1797 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1798 "open", 1799 filename); 1800 return GNUNET_OK; 1801 } 1802 if (0 != fstat (fd, 1803 &sbuf)) 1804 { 1805 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1806 "stat", 1807 filename); 1808 GNUNET_break (0 == close (fd)); 1809 return GNUNET_OK; 1810 } 1811 if (! S_ISREG (sbuf.st_mode)) 1812 { 1813 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1814 "File `%s' is not a regular file, which is not allowed for private keys!\n", 1815 filename); 1816 GNUNET_break (0 == close (fd)); 1817 return GNUNET_OK; 1818 } 1819 if (0 != (sbuf.st_mode & (S_IWUSR | S_IRWXG | S_IRWXO))) 1820 { 1821 /* permission are NOT tight, try to patch them up! */ 1822 if (0 != 1823 fchmod (fd, 1824 S_IRUSR)) 1825 { 1826 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1827 "fchmod", 1828 filename); 1829 /* refuse to use key if file has wrong permissions */ 1830 GNUNET_break (0 == close (fd)); 1831 return GNUNET_OK; 1832 } 1833 } 1834 fh = GNUNET_DISK_get_handle_from_int_fd (fd); 1835 if (NULL == fh) 1836 { 1837 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1838 "open", 1839 filename); 1840 GNUNET_break (0 == close (fd)); 1841 return GNUNET_OK; 1842 } 1843 if (sbuf.st_size > 16 * 1024) 1844 { 1845 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1846 "File `%s' too big to be a private key\n", 1847 filename); 1848 GNUNET_DISK_file_close (fh); 1849 return GNUNET_OK; 1850 } 1851 ptr = GNUNET_DISK_file_map (fh, 1852 &map, 1853 GNUNET_DISK_MAP_TYPE_READ, 1854 (size_t) sbuf.st_size); 1855 if (NULL == ptr) 1856 { 1857 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, 1858 "mmap", 1859 filename); 1860 GNUNET_DISK_file_close (fh); 1861 return GNUNET_OK; 1862 } 1863 parse_key (denom, 1864 filename, 1865 ptr, 1866 (size_t) sbuf.st_size); 1867 GNUNET_DISK_file_unmap (map); 1868 GNUNET_DISK_file_close (fh); 1869 return GNUNET_OK; 1870 } 1871 1872 1873 /** 1874 * Parse configuration for denomination type parameters. Also determines 1875 * our anchor by looking at the existing denominations of the same type. 1876 * 1877 * @param cfg configuration to use 1878 * @param ct section in the configuration file giving the denomination type parameters 1879 * @param[out] denom set to the denomination parameters from the configuration 1880 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid 1881 */ 1882 static enum GNUNET_GenericReturnValue 1883 parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, 1884 const char *ct, 1885 struct Denomination *denom) 1886 { 1887 unsigned long long rsa_keysize; 1888 char *secname; 1889 1890 GNUNET_asprintf (&secname, 1891 "%s-secmod-rsa", 1892 globals->section); 1893 if (GNUNET_OK != 1894 GNUNET_CONFIGURATION_get_value_time (cfg, 1895 ct, 1896 "DURATION_WITHDRAW", 1897 &denom->duration_withdraw)) 1898 { 1899 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 1900 ct, 1901 "DURATION_WITHDRAW"); 1902 GNUNET_free (secname); 1903 return GNUNET_SYSERR; 1904 } 1905 if (GNUNET_TIME_relative_cmp (denom->duration_withdraw, 1906 <, 1907 GNUNET_TIME_UNIT_SECONDS)) 1908 { 1909 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 1910 ct, 1911 "DURATION_WITHDRAW", 1912 "less than one second is not supported"); 1913 GNUNET_free (secname); 1914 return GNUNET_SYSERR; 1915 } 1916 if (GNUNET_TIME_relative_cmp (overlap_duration, 1917 >=, 1918 denom->duration_withdraw)) 1919 { 1920 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 1921 secname, 1922 "OVERLAP_DURATION", 1923 "Value given must be smaller than value for DURATION_WITHDRAW!"); 1924 GNUNET_free (secname); 1925 return GNUNET_SYSERR; 1926 } 1927 { 1928 struct GNUNET_TIME_Relative ar; 1929 1930 /* The denomination section takes precedence, the secmod section 1931 provides the default for all denominations. */ 1932 if ( (GNUNET_OK != 1933 GNUNET_CONFIGURATION_get_value_time (cfg, 1934 ct, 1935 "ANCHOR_ROUND", 1936 &ar)) && 1937 (GNUNET_OK != 1938 GNUNET_CONFIGURATION_get_value_time (cfg, 1939 secname, 1940 "ANCHOR_ROUND", 1941 &ar)) ) 1942 ar = GNUNET_TIME_UNIT_ZERO; /* not configured: do not round */ 1943 denom->anchor_round 1944 = GNUNET_TIME_relative_to_round_interval (ar); 1945 if ( (GNUNET_TIME_RI_NONE == denom->anchor_round) && 1946 (! GNUNET_TIME_relative_is_zero (ar)) ) 1947 { 1948 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 1949 ct, 1950 "ANCHOR_ROUND", 1951 "Value given must be zero or exactly one second, minute, hour, day, week, month, quarter or year"); 1952 GNUNET_free (secname); 1953 return GNUNET_SYSERR; 1954 } 1955 } 1956 if (GNUNET_OK != 1957 GNUNET_CONFIGURATION_get_value_number (cfg, 1958 ct, 1959 "RSA_KEYSIZE", 1960 &rsa_keysize)) 1961 { 1962 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 1963 ct, 1964 "RSA_KEYSIZE"); 1965 GNUNET_free (secname); 1966 return GNUNET_SYSERR; 1967 } 1968 if ( (rsa_keysize > 4 * 2048) || 1969 (rsa_keysize < 1024) ) 1970 { 1971 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, 1972 ct, 1973 "RSA_KEYSIZE", 1974 "Given RSA keysize outside of permitted range [1024,8192]\n"); 1975 GNUNET_free (secname); 1976 return GNUNET_SYSERR; 1977 } 1978 GNUNET_free (secname); 1979 denom->rsa_keysize = (unsigned int) rsa_keysize; 1980 denom->section = GNUNET_strdup (ct); 1981 return GNUNET_OK; 1982 } 1983 1984 1985 /** 1986 * Closure for #load_denominations. 1987 */ 1988 struct LoadContext 1989 { 1990 1991 /** 1992 * Configuration to use. 1993 */ 1994 const struct GNUNET_CONFIGURATION_Handle *cfg; 1995 1996 /** 1997 * Configuration section prefix to use for denomination settings. 1998 * "coin_" for the exchange, "doco_" for Donau. 1999 */ 2000 const char *cprefix; 2001 2002 /** 2003 * Status, to be set to #GNUNET_SYSERR on failure 2004 */ 2005 enum GNUNET_GenericReturnValue ret; 2006 }; 2007 2008 2009 /** 2010 * Generate new denomination signing keys for the denomination type of the given @a 2011 * denomination_alias. 2012 * 2013 * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure 2014 * @param denomination_alias name of the denomination's section in the configuration 2015 */ 2016 static void 2017 load_denominations (void *cls, 2018 const char *denomination_alias) 2019 { 2020 struct LoadContext *ctx = cls; 2021 struct Denomination *denom; 2022 char *cipher; 2023 2024 if (0 != strncasecmp (denomination_alias, 2025 ctx->cprefix, 2026 strlen (ctx->cprefix))) 2027 return; /* not a denomination type definition */ 2028 if (GNUNET_OK != 2029 GNUNET_CONFIGURATION_get_value_string (ctx->cfg, 2030 denomination_alias, 2031 "CIPHER", 2032 &cipher)) 2033 { 2034 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2035 denomination_alias, 2036 "CIPHER"); 2037 return; 2038 } 2039 if (0 != strcmp (cipher, 2040 "RSA")) 2041 { 2042 GNUNET_free (cipher); 2043 return; /* Ignore denominations of other types than CS */ 2044 } 2045 GNUNET_free (cipher); 2046 denom = GNUNET_new (struct Denomination); 2047 if (GNUNET_OK != 2048 parse_denomination_cfg (ctx->cfg, 2049 denomination_alias, 2050 denom)) 2051 { 2052 ctx->ret = GNUNET_SYSERR; 2053 GNUNET_free (denom); 2054 return; 2055 } 2056 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 2057 "Loading keys for denomination %s\n", 2058 denom->section); 2059 { 2060 char *dname; 2061 2062 GNUNET_asprintf (&dname, 2063 "%s/%s", 2064 keydir, 2065 denom->section); 2066 GNUNET_break (GNUNET_OK == 2067 GNUNET_DISK_directory_create (dname)); 2068 GNUNET_DISK_directory_scan (dname, 2069 &import_key, 2070 denom); 2071 GNUNET_free (dname); 2072 } 2073 GNUNET_CONTAINER_DLL_insert (denom_head, 2074 denom_tail, 2075 denom); 2076 } 2077 2078 2079 /** 2080 * Load the various duration values from @a cfg 2081 * 2082 * @param cfg configuration to use 2083 * @return #GNUNET_OK on success 2084 */ 2085 static enum GNUNET_GenericReturnValue 2086 load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg) 2087 { 2088 char *secname; 2089 2090 GNUNET_asprintf (&secname, 2091 "%s-secmod-rsa", 2092 globals->section); 2093 if (GNUNET_OK != 2094 GNUNET_CONFIGURATION_get_value_time (cfg, 2095 secname, 2096 "OVERLAP_DURATION", 2097 &overlap_duration)) 2098 { 2099 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2100 secname, 2101 "OVERLAP_DURATION"); 2102 GNUNET_free (secname); 2103 return GNUNET_SYSERR; 2104 } 2105 if (GNUNET_OK != 2106 GNUNET_CONFIGURATION_get_value_time (cfg, 2107 secname, 2108 "LOOKAHEAD_SIGN", 2109 &lookahead_sign)) 2110 { 2111 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2112 secname, 2113 "LOOKAHEAD_SIGN"); 2114 GNUNET_free (secname); 2115 return GNUNET_SYSERR; 2116 } 2117 GNUNET_free (secname); 2118 return GNUNET_OK; 2119 } 2120 2121 2122 /** 2123 * Function run on shutdown. Stops the various jobs (nicely). 2124 * 2125 * @param cls NULL 2126 */ 2127 static void 2128 do_shutdown (void *cls) 2129 { 2130 (void) cls; 2131 TES_listen_stop (); 2132 if (NULL != keygen_task) 2133 { 2134 GNUNET_SCHEDULER_cancel (keygen_task); 2135 keygen_task = NULL; 2136 } 2137 stop_workers (); 2138 sem_done (&worker_sem); 2139 } 2140 2141 2142 void 2143 TALER_SECMOD_rsa_run (void *cls, 2144 char *const *args, 2145 const char *cfgfile, 2146 const struct GNUNET_CONFIGURATION_Handle *cfg) 2147 { 2148 static struct TES_Callbacks cb = { 2149 .dispatch = rsa_work_dispatch, 2150 .updater = rsa_update_client_keys, 2151 .init = rsa_client_init 2152 }; 2153 struct TALER_SECMOD_Options *opt = cls; 2154 char *secname; 2155 2156 (void) args; 2157 (void) cfgfile; 2158 globals = opt; 2159 if (GNUNET_TIME_timestamp_cmp (opt->global_now, 2160 !=, 2161 opt->global_now_tmp)) 2162 { 2163 /* The user gave "--now", use it! */ 2164 opt->global_now = opt->global_now_tmp; 2165 } 2166 else 2167 { 2168 /* get current time again, we may be timetraveling! */ 2169 opt->global_now = GNUNET_TIME_timestamp_get (); 2170 } 2171 GNUNET_asprintf (&secname, 2172 "%s-secmod-rsa", 2173 opt->section); 2174 if (GNUNET_OK != 2175 GNUNET_CONFIGURATION_get_value_filename (cfg, 2176 secname, 2177 "KEY_DIR", 2178 &keydir)) 2179 { 2180 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 2181 secname, 2182 "KEY_DIR"); 2183 GNUNET_free (secname); 2184 opt->global_ret = EXIT_NOTCONFIGURED; 2185 return; 2186 } 2187 if (GNUNET_OK != 2188 load_durations (cfg)) 2189 { 2190 opt->global_ret = EXIT_NOTCONFIGURED; 2191 GNUNET_free (secname); 2192 return; 2193 } 2194 opt->global_ret = TES_listen_start (cfg, 2195 secname, 2196 &cb); 2197 GNUNET_free (secname); 2198 if (0 != opt->global_ret) 2199 return; 2200 sem_init (&worker_sem, 2201 0); 2202 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 2203 NULL); 2204 if (0 == opt->max_workers) 2205 { 2206 long lret; 2207 2208 lret = sysconf (_SC_NPROCESSORS_CONF); 2209 if (lret <= 0) 2210 lret = 1; 2211 opt->max_workers = (unsigned int) lret; 2212 } 2213 2214 for (unsigned int i = 0; i<opt->max_workers; i++) 2215 if (GNUNET_OK != 2216 start_worker ()) 2217 { 2218 GNUNET_SCHEDULER_shutdown (); 2219 return; 2220 } 2221 /* Load denominations */ 2222 keys = GNUNET_CONTAINER_multihashmap_create (65536, 2223 true); 2224 { 2225 struct LoadContext lc = { 2226 .cfg = cfg, 2227 .ret = GNUNET_OK, 2228 .cprefix = opt->cprefix 2229 }; 2230 bool wake = true; 2231 2232 GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); 2233 GNUNET_CONFIGURATION_iterate_sections (cfg, 2234 &load_denominations, 2235 &lc); 2236 GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); 2237 if (GNUNET_OK != lc.ret) 2238 { 2239 opt->global_ret = EXIT_FAILURE; 2240 GNUNET_SCHEDULER_shutdown (); 2241 return; 2242 } 2243 create_missing_keys (opt, 2244 &wake); 2245 } 2246 if (NULL == denom_head) 2247 { 2248 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2249 "No RSA denominations configured. Make sure section names start with `%s' if you are using RSA!\n", 2250 opt->cprefix); 2251 TES_wake_clients (); 2252 return; 2253 } 2254 /* start job to keep keys up-to-date; MUST be run before the #listen_task, 2255 hence with priority. */ 2256 keygen_task = GNUNET_SCHEDULER_add_with_priority ( 2257 GNUNET_SCHEDULER_PRIORITY_URGENT, 2258 &update_denominations, 2259 opt); 2260 }